From python-checkins at python.org Sat Sep 1 00:52:50 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 1 Sep 2012 00:52:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Differentiate_between_l?= =?utf-8?q?ibraries_that_are_Python_3_compatible_as-is_vs=2E?= Message-ID: <3X7wnt72YtzQLj@mail.python.org> http://hg.python.org/benchmarks/rev/47035700a022 changeset: 163:47035700a022 user: Brett Cannon date: Fri Aug 31 18:52:42 2012 -0400 summary: Differentiate between libraries that are Python 3 compatible as-is vs. needing 2to3 translation. files: make_perf3.sh | 11 +++++++++-- 1 files changed, 9 insertions(+), 2 deletions(-) diff --git a/make_perf3.sh b/make_perf3.sh --- a/make_perf3.sh +++ b/make_perf3.sh @@ -30,9 +30,16 @@ cp "${srcdir}/perf.py" perf.py ${CONVERT} perf.py -SAFE_LIBS="2to3 mako pathlib" +# Libraries that are Python 3 compatible as-is. +SAFE_LIBS_AS_IS="pathlib" +# Libraries that work with Python 3 after passing through 2to3. +SAFE_LIBS_TO_TRANSLATE="2to3 mako" mkdir lib -for safe_lib in ${SAFE_LIBS}; do +for safe_lib in ${SAFE_LIBS_AS_IS}; do + cp -a "${srcdir}/lib/${safe_lib}" lib/${safe_lib} +done + +for safe_lib in ${SAFE_LIBS_TO_TRANSLATE}; do cp -a "${srcdir}/lib/${safe_lib}" lib/${safe_lib} ${CONVERT} lib/${safe_lib} done -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 1 00:58:32 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 1 Sep 2012 00:58:32 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Allow_for_the_specifica?= =?utf-8?q?tion_of_a_base_directory_for_either_interpreter?= Message-ID: <3X7wwS2MjFzPyh@mail.python.org> http://hg.python.org/benchmarks/rev/61768f86170c changeset: 164:61768f86170c user: Brett Cannon date: Fri Aug 31 18:58:24 2012 -0400 summary: Allow for the specification of a base directory for either interpreter being run. This allows for comparing Python 2.x to Python 3.x by having a Python 2 copy of the benchmarks and Python 3 copy of the benchmarks and then specifying the proper directory:: benchmarks_py3k$ python3 perf.py --basedir /some/py2/benchmark `which python2.7` `which python3.2` files: perf.py | 39 ++++++++++++++++++++++++++++++++------- 1 files changed, 32 insertions(+), 7 deletions(-) diff --git a/perf.py b/perf.py --- a/perf.py +++ b/perf.py @@ -850,8 +850,14 @@ "-exec", "rm", "-f", "{}", ";"]) -def Relative(path): - return os.path.join(os.path.dirname(__file__), path) +def Relative(path, python=None, options=None): + basedir = os.path.dirname(__file__) + if python is not None: + if python[0] == options.base_binary: + basedir = options.control_dirname + else: + basedir = options.experimental_dirname + return os.path.join(basedir, path) def LogCall(command): @@ -1258,9 +1264,9 @@ def Measure2to3(python, options): - fast_target = Relative("lib/2to3/lib2to3/refactor.py") - two_to_three_bin = Relative("lib/2to3/2to3") - two_to_three_dir = Relative("lib/2to3_data") + fast_target = Relative("lib/2to3/lib2to3/refactor.py", python, options) + two_to_three_bin = Relative("lib/2to3/2to3", python, options) + two_to_three_dir = Relative("lib/2to3_data", python, options) env = BuildEnv({"PYTHONPATH": two_to_three_dir}, inherit_env=options.inherit_env) @@ -1471,8 +1477,8 @@ def MeasureMako(python, options): - bm_path = Relative("performance/bm_mako.py") - mako_path = Relative("lib/mako") + bm_path = Relative("performance/bm_mako.py", python, options) + mako_path = Relative("lib/mako", python, options) bm_env = BuildEnv({"PYTHONPATH": mako_path}, options.inherit_env) return MeasureGeneric(python, options, bm_path, bm_env, iteration_scaling=5) @@ -2086,6 +2092,13 @@ """Parser callback to --inherit_env var names.""" parser.values.inherit_env = [v for v in value.split(",") if v] +def ParseBasedirOption(python_args_opt): + default = os.path.dirname(__file__) + parts = python_args_opt.split(",") + if len(parts) == 1: # No comma + parts.append('') + return [path or default for path in parts] + def ParseOutputStyle(option, opt_str, value, parser): if value not in ("normal", "table"): @@ -2142,6 +2155,15 @@ help=("Comma-separated list of environment variable names" " that are inherited from the parent environment" " when running benchmarking subprocesses.")) + parser.add_option("--basedir", default="", + help=("A comma-separated pair of base directories to " + "use when calculating absolute file paths to " + "benchmark and library code. The first argument " + "is for the base interpreter, the second for the " + "experimental one. Any unspecified value is " + "assumed to be the directory containing this " + "file. This is typically used when comparing a " + "Python 2.x interpreter to a 3.x one.")) parser.add_option("-T", "--disable_timelines", default=False, action="store_true", help="Don't use Google charts for displaying timelines.") parser.add_option("-O", "--output_style", metavar="STYLE", type="string", @@ -2184,6 +2206,9 @@ base_cmd_prefix = [base] + base_args changed_cmd_prefix = [changed] + changed_args + basedirs = ParseBasedirOption(options.basedir) + options.control_dirname, options.experimental_dirname = basedirs + logging.basicConfig(level=logging.INFO) if options.track_memory: -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 1 05:16:49 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 1 Sep 2012 05:16:49 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzEyNzc2LCMxMTgz?= =?utf-8?q?9=3A_call_argparse_type_function_only_once=2E?= Message-ID: <3X82fT2R8dzQTl@mail.python.org> http://hg.python.org/cpython/rev/1b614921aefa changeset: 78821:1b614921aefa branch: 3.2 parent: 78818:c0c7b1998306 user: R David Murray date: Fri Aug 31 22:45:20 2012 -0400 summary: #12776,#11839: call argparse type function only once. Before, the type function was called twice in the case where the default was specified and the argument was given as well. This was especially problematic for the FileType type, as a default file would always be opened, even if a file argument was specified on the command line. Patch by Arnaud Fontaine, with additional test by Mike Meyer. files: Lib/argparse.py | 21 +++++++--- Lib/test/test_argparse.py | 48 +++++++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 6 +++ 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1714,10 +1714,7 @@ if action.dest is not SUPPRESS: if not hasattr(namespace, action.dest): if action.default is not SUPPRESS: - default = action.default - if isinstance(action.default, str): - default = self._get_value(action, default) - setattr(namespace, action.dest, default) + setattr(namespace, action.dest, action.default) # add any parser defaults that aren't present for dest in self._defaults: @@ -1945,12 +1942,22 @@ if positionals: self.error(_('too few arguments')) - # make sure all required actions were present + # make sure all required actions were present, and convert defaults. for action in self._actions: - if action.required: - if action not in seen_actions: + if action not in seen_actions: + if action.required: name = _get_action_name(action) self.error(_('argument %s is required') % name) + else: + # Convert action default now instead of doing it before + # parsing arguments to avoid calling convert functions + # twice (which may fail) if the argument was given, but + # only if it was defined already in the namespace + if (action.default is not None and + hasattr(namespace, action.dest) and + action.default is getattr(namespace, action.dest)): + setattr(namespace, action.dest, + self._get_value(action, action.default)) # make sure all required groups had one option present for group in self._mutually_exclusive_groups: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1462,6 +1462,22 @@ ('readonly', NS(x=None, spam=RFile('readonly'))), ] +class TestFileTypeDefaults(TempDirMixin, ParserTestCase): + """Test that a file is not created unless the default is needed""" + def setUp(self): + super(TestFileTypeDefaults, self).setUp() + file = open(os.path.join(self.temp_dir, 'good'), 'w') + file.write('good') + file.close() + + argument_signatures = [ + Sig('-c', type=argparse.FileType('r'), default='no-file.txt'), + ] + # should provoke no such file error + failures = [''] + # should not provoke error because default file is created + successes = [('-c good', NS(c=RFile('good')))] + class TestFileTypeRB(TempDirMixin, ParserTestCase): """Test the FileType option/argument type for reading files""" @@ -4468,6 +4484,38 @@ else: self.fail() +# ================================================ +# Check that the type function is called only once +# ================================================ + +class TestTypeFunctionCallOnlyOnce(TestCase): + + def test_type_function_call_only_once(self): + def spam(string_to_convert): + self.assertEqual(string_to_convert, 'spam!') + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default='bar') + args = parser.parse_args('--foo spam!'.split()) + self.assertEqual(NS(foo='foo_converted'), args) + +# ================================================================ +# Check that the type function is called with a non-string default +# ================================================================ + +class TestTypeFunctionCallWithNonStringDefault(TestCase): + + def test_type_function_call_with_non_string_default(self): + def spam(int_to_convert): + self.assertEqual(int_to_convert, 0) + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default=0) + args = parser.parse_args([]) + self.assertEqual(NS(foo='foo_converted'), args) + # ====================== # parse_known_args tests # ====================== diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -305,6 +305,7 @@ Frederik Fix Matt Fleming Hern?n Mart?nez Foffani +Arnaud Fontaine Michael Foord Amaury Forgeot d'Arc Doug Fort diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -112,6 +112,12 @@ Library ------- +- Issue #12776,#11839: call argparse type function (specified by add_argument) + only once. Before, the type function was called twice in the case where the + default was specified and the argument was given as well. This was + especially problematic for the FileType type, as a default file would always + be opened, even if a file argument was specified on the command line. + - Issue #13370: Ensure that ctypes works on Mac OS X when Python is compiled using the clang compiler -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 05:16:51 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 1 Sep 2012 05:16:51 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2312776=2C=2311839=3A_call_argparse_type_function?= =?utf-8?q?_only_once=2E?= Message-ID: <3X82fW1lylzQTl@mail.python.org> http://hg.python.org/cpython/rev/74f6d87cd471 changeset: 78822:74f6d87cd471 parent: 78819:815b88454e3e parent: 78821:1b614921aefa user: R David Murray date: Fri Aug 31 23:09:34 2012 -0400 summary: Merge #12776,#11839: call argparse type function only once. Before, the type function was called twice in the case where the default was specified and the argument was given as well. This was especially problematic for the FileType type, as a default file would always be opened, even if a file argument was specified on the command line. Patch by Arnaud Fontaine, with additional test by Mike Meyer. files: Lib/argparse.py | 26 ++++++++++--- Lib/test/test_argparse.py | 48 +++++++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 6 +++ 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1722,10 +1722,7 @@ if action.dest is not SUPPRESS: if not hasattr(namespace, action.dest): if action.default is not SUPPRESS: - default = action.default - if isinstance(action.default, str): - default = self._get_value(action, default) - setattr(namespace, action.dest, default) + setattr(namespace, action.dest, action.default) # add any parser defaults that aren't present for dest in self._defaults: @@ -1948,9 +1945,24 @@ # if we didn't consume all the argument strings, there were extras extras.extend(arg_strings[stop_index:]) - # make sure all required actions were present - required_actions = [_get_action_name(action) for action in self._actions - if action.required and action not in seen_actions] + # make sure all required actions were present and also convert + # action defaults which were not given as arguments + required_actions = [] + for action in self._actions: + if action not in seen_actions: + if action.required: + required_actions.append(_get_action_name(action)) + else: + # Convert action default now instead of doing it before + # parsing arguments to avoid calling convert functions + # twice (which may fail) if the argument was given, but + # only if it was defined already in the namespace + if (action.default is not None and + hasattr(namespace, action.dest) and + action.default is getattr(namespace, action.dest)): + setattr(namespace, action.dest, + self._get_value(action, action.default)) + if required_actions: self.error(_('the following arguments are required: %s') % ', '.join(required_actions)) diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1463,6 +1463,22 @@ ('readonly', NS(x=None, spam=RFile('readonly'))), ] +class TestFileTypeDefaults(TempDirMixin, ParserTestCase): + """Test that a file is not created unless the default is needed""" + def setUp(self): + super(TestFileTypeDefaults, self).setUp() + file = open(os.path.join(self.temp_dir, 'good'), 'w') + file.write('good') + file.close() + + argument_signatures = [ + Sig('-c', type=argparse.FileType('r'), default='no-file.txt'), + ] + # should provoke no such file error + failures = [''] + # should not provoke error because default file is created + successes = [('-c good', NS(c=RFile('good')))] + class TestFileTypeRB(TempDirMixin, ParserTestCase): """Test the FileType option/argument type for reading files""" @@ -4559,6 +4575,38 @@ self.assertNotIn(msg, 'optional_positional') +# ================================================ +# Check that the type function is called only once +# ================================================ + +class TestTypeFunctionCallOnlyOnce(TestCase): + + def test_type_function_call_only_once(self): + def spam(string_to_convert): + self.assertEqual(string_to_convert, 'spam!') + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default='bar') + args = parser.parse_args('--foo spam!'.split()) + self.assertEqual(NS(foo='foo_converted'), args) + +# ================================================================ +# Check that the type function is called with a non-string default +# ================================================================ + +class TestTypeFunctionCallWithNonStringDefault(TestCase): + + def test_type_function_call_with_non_string_default(self): + def spam(int_to_convert): + self.assertEqual(int_to_convert, 0) + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default=0) + args = parser.parse_args([]) + self.assertEqual(NS(foo='foo_converted'), args) + # ====================== # parse_known_args tests # ====================== diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -335,6 +335,7 @@ Frederik Fix Matt Fleming Hern?n Mart?nez Foffani +Arnaud Fontaine Michael Foord Amaury Forgeot d'Arc Doug Fort diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -16,6 +16,12 @@ Library ------- +- Issue #12776,#11839: call argparse type function (specified by add_argument) + only once. Before, the type function was called twice in the case where the + default was specified and the argument was given as well. This was + especially problematic for the FileType type, as a default file would always + be opened, even if a file argument was specified on the command line. + Extension Modules ----------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 05:16:52 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 1 Sep 2012 05:16:52 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzEyNzc2LCMxMTgz?= =?utf-8?q?9=3A_call_argparse_type_function_only_once=2E?= Message-ID: <3X82fX64QmzQSt@mail.python.org> http://hg.python.org/cpython/rev/62b5667ef2f4 changeset: 78823:62b5667ef2f4 branch: 2.7 parent: 78820:7b076911f5f9 user: R David Murray date: Fri Aug 31 23:15:28 2012 -0400 summary: #12776,#11839: call argparse type function only once. Before, the type function was called twice in the case where the default was specified and the argument was given as well. This was especially problematic for the FileType type, as a default file would always be opened, even if a file argument was specified on the command line. Patch by Arnaud Fontaine, with additional test by Mike Meyer. files: Lib/argparse.py | 21 +++++++--- Lib/test/test_argparse.py | 48 +++++++++++++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 6 +++ 4 files changed, 69 insertions(+), 7 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1705,10 +1705,7 @@ if action.dest is not SUPPRESS: if not hasattr(namespace, action.dest): if action.default is not SUPPRESS: - default = action.default - if isinstance(action.default, basestring): - default = self._get_value(action, default) - setattr(namespace, action.dest, default) + setattr(namespace, action.dest, action.default) # add any parser defaults that aren't present for dest in self._defaults: @@ -1936,12 +1933,22 @@ if positionals: self.error(_('too few arguments')) - # make sure all required actions were present + # make sure all required actions were present, and convert defaults. for action in self._actions: - if action.required: - if action not in seen_actions: + if action not in seen_actions: + if action.required: name = _get_action_name(action) self.error(_('argument %s is required') % name) + else: + # Convert action default now instead of doing it before + # parsing arguments to avoid calling convert functions + # twice (which may fail) if the argument was given, but + # only if it was defined already in the namespace + if (action.default is not None and + hasattr(namespace, action.dest) and + action.default is getattr(namespace, action.dest)): + setattr(namespace, action.dest, + self._get_value(action, action.default)) # make sure all required groups had one option present for group in self._mutually_exclusive_groups: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -1467,6 +1467,22 @@ ('readonly', NS(x=None, spam=RFile('readonly'))), ] +class TestFileTypeDefaults(TempDirMixin, ParserTestCase): + """Test that a file is not created unless the default is needed""" + def setUp(self): + super(TestFileTypeDefaults, self).setUp() + file = open(os.path.join(self.temp_dir, 'good'), 'w') + file.write('good') + file.close() + + argument_signatures = [ + Sig('-c', type=argparse.FileType('r'), default='no-file.txt'), + ] + # should provoke no such file error + failures = [''] + # should not provoke error because default file is created + successes = [('-c good', NS(c=RFile('good')))] + class TestFileTypeRB(TempDirMixin, ParserTestCase): """Test the FileType option/argument type for reading files""" @@ -4432,6 +4448,38 @@ else: self.fail() +# ================================================ +# Check that the type function is called only once +# ================================================ + +class TestTypeFunctionCallOnlyOnce(TestCase): + + def test_type_function_call_only_once(self): + def spam(string_to_convert): + self.assertEqual(string_to_convert, 'spam!') + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default='bar') + args = parser.parse_args('--foo spam!'.split()) + self.assertEqual(NS(foo='foo_converted'), args) + +# ================================================================ +# Check that the type function is called with a non-string default +# ================================================================ + +class TestTypeFunctionCallWithNonStringDefault(TestCase): + + def test_type_function_call_with_non_string_default(self): + def spam(int_to_convert): + self.assertEqual(int_to_convert, 0) + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default=0) + args = parser.parse_args([]) + self.assertEqual(NS(foo='foo_converted'), args) + # ====================== # parse_known_args tests # ====================== diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -271,6 +271,7 @@ Frederik Fix Matt Fleming Hern?n Mart?nez Foffani +Arnaud Fontaine Michael Foord Amaury Forgeot d'Arc Doug Fort diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -98,6 +98,12 @@ Library ------- +- Issue #12776,#11839: call argparse type function (specified by add_argument) + only once. Before, the type function was called twice in the case where the + default was specified and the argument was given as well. This was + especially problematic for the FileType type, as a default file would always + be opened, even if a file argument was specified on the command line. + - Issue #13370: Ensure that ctypes works on Mac OS X when Python is compiled using the clang compiler -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Sep 1 06:02:21 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 01 Sep 2012 06:02:21 +0200 Subject: [Python-checkins] Daily reference leaks (815b88454e3e): sum=0 Message-ID: results for 815b88454e3e on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogtCRzFU', '-x'] From python-checkins at python.org Sat Sep 1 06:31:53 2012 From: python-checkins at python.org (petri.lehtinen) Date: Sat, 1 Sep 2012 06:31:53 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzEzNzY5OiBFbmhh?= =?utf-8?q?nce_docs_for_ensure=5Fascii_semantics_in_JSON_decoding_function?= =?utf-8?q?s?= Message-ID: <3X84K516KVzQNR@mail.python.org> http://hg.python.org/cpython/rev/a1884b3027c5 changeset: 78824:a1884b3027c5 branch: 2.7 user: Petri Lehtinen date: Sat Sep 01 07:27:58 2012 +0300 summary: #13769: Enhance docs for ensure_ascii semantics in JSON decoding functions files: Doc/library/json.rst | 30 ++++++++++++++++++------------ Lib/json/__init__.py | 18 ++++++++++-------- Lib/json/encoder.py | 9 ++++++--- Misc/NEWS | 3 +++ 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/Doc/library/json.rst b/Doc/library/json.rst --- a/Doc/library/json.rst +++ b/Doc/library/json.rst @@ -127,11 +127,14 @@ :class:`float`, :class:`bool`, ``None``) will be skipped instead of raising a :exc:`TypeError`. - If *ensure_ascii* is ``False`` (default: ``True``), then some chunks written - to *fp* may be :class:`unicode` instances, subject to normal Python - :class:`str` to :class:`unicode` coercion rules. Unless ``fp.write()`` - explicitly understands :class:`unicode` (as in :func:`codecs.getwriter`) this - is likely to cause an error. + If *ensure_ascii* is ``True`` (the default), all non-ASCII characters in the + output are escaped with ``\uXXXX`` sequences, and the result is a + :class:`str` instance consisting of ASCII characters only. If + *ensure_ascii* is ``False``, some chunks written to *fp* may be + :class:`unicode` instances. This usually happens because the input contains + unicode strings or the *encoding* parameter is used. Unless ``fp.write()`` + explicitly understands :class:`unicode` (as in :func:`codecs.getwriter`) + this is likely to cause an error. If *check_circular* is ``False`` (default: ``True``), then the circular reference check for container types will be skipped and a circular reference @@ -168,11 +171,11 @@ .. function:: dumps(obj[, skipkeys[, ensure_ascii[, check_circular[, allow_nan[, cls[, indent[, separators[, encoding[, default[, **kw]]]]]]]]]]) - Serialize *obj* to a JSON formatted :class:`str`. + Serialize *obj* to a JSON formatted :class:`str`. If *ensure_ascii* is + ``False``, the result may contain non-ASCII characters and the return value + may be a :class:`unicode` instance. - If *ensure_ascii* is ``False``, then the return value will be a - :class:`unicode` instance. The other arguments have the same meaning as in - :func:`dump`. + The arguments have the same meaning as in :func:`dump`. .. note:: @@ -371,9 +374,12 @@ attempt encoding of keys that are not str, int, long, float or None. If *skipkeys* is ``True``, such items are simply skipped. - If *ensure_ascii* is ``True`` (the default), the output is guaranteed to be - :class:`str` objects with all incoming unicode characters escaped. If - *ensure_ascii* is ``False``, the output will be a unicode object. + If *ensure_ascii* is ``True`` (the default), all non-ASCII characters in the + output are escaped with ``\uXXXX`` sequences, and the results are + :class:`str` instances consisting of ASCII characters only. If + *ensure_ascii* is ``False``, a result may be a :class:`unicode` + instance. This usually happens if the input contains unicode strings or the + *encoding* parameter is used. If *check_circular* is ``True`` (the default), then lists, dicts, and custom encoded objects will be checked for circular references during encoding to diff --git a/Lib/json/__init__.py b/Lib/json/__init__.py --- a/Lib/json/__init__.py +++ b/Lib/json/__init__.py @@ -129,11 +129,14 @@ (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. - If ``ensure_ascii`` is false, then the some chunks written to ``fp`` - may be ``unicode`` instances, subject to normal Python ``str`` to - ``unicode`` coercion rules. Unless ``fp.write()`` explicitly - understands ``unicode`` (as in ``codecs.getwriter()``) this is likely - to cause an error. + If ``ensure_ascii`` is true (the default), all non-ASCII characters in the + output are escaped with ``\uXXXX`` sequences, and the result is a ``str`` + instance consisting of ASCII characters only. If ``ensure_ascii`` is + ``False``, some chunks written to ``fp`` may be ``unicode`` instances. + This usually happens because the input contains unicode strings or the + ``encoding`` parameter is used. Unless ``fp.write()`` explicitly + understands ``unicode`` (as in ``codecs.getwriter``) this is likely to + cause an error. If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will @@ -191,9 +194,8 @@ (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``) will be skipped instead of raising a ``TypeError``. - If ``ensure_ascii`` is false, then the return value will be a - ``unicode`` instance subject to normal Python ``str`` to ``unicode`` - coercion rules instead of being escaped to an ASCII ``str``. + If ``ensure_ascii`` is false, all non-ASCII characters are not escaped, and + the return value may be a ``unicode`` instance. See ``dump`` for details. If ``check_circular`` is false, then the circular reference check for container types will be skipped and a circular reference will diff --git a/Lib/json/encoder.py b/Lib/json/encoder.py --- a/Lib/json/encoder.py +++ b/Lib/json/encoder.py @@ -107,9 +107,12 @@ encoding of keys that are not str, int, long, float or None. If skipkeys is True, such items are simply skipped. - If ensure_ascii is true, the output is guaranteed to be str - objects with all incoming unicode characters escaped. If - ensure_ascii is false, the output will be unicode object. + If *ensure_ascii* is true (the default), all non-ASCII + characters in the output are escaped with \uXXXX sequences, + and the results are str instances consisting of ASCII + characters only. If ensure_ascii is False, a result may be a + unicode instance. This usually happens if the input contains + unicode strings or the *encoding* parameter is used. If check_circular is true, then lists, dicts, and custom encoded objects will be checked for circular references during encoding to diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -393,6 +393,9 @@ Documentation ------------- +- Issue #13769: Document the effect of ensure_ascii to the return type + of JSON decoding functions. + - Issue #14880: Fix kwargs notation in csv.reader, .writer & .register_dialect. Patch by Chris Rebert. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 13:30:46 2012 From: python-checkins at python.org (petri.lehtinen) Date: Sat, 1 Sep 2012 13:30:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1ODAyOiBGaXgg?= =?utf-8?q?test_logic_in_TestMaildir=2Etest=5Fcreate=5Ftmp?= Message-ID: <3X8FcQ1RDXzQNS@mail.python.org> http://hg.python.org/cpython/rev/aef4a2ba3210 changeset: 78825:aef4a2ba3210 branch: 3.2 parent: 78821:1b614921aefa user: Petri Lehtinen date: Sat Sep 01 14:22:36 2012 +0300 summary: #15802: Fix test logic in TestMaildir.test_create_tmp files: Lib/test/test_mailbox.py | 10 +++++----- Misc/NEWS | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -759,13 +759,13 @@ self.assertIsNot(match, None, "Invalid file name: '%s'" % tail) groups = match.groups() if previous_groups is not None: - self.assertTrue(int(groups[0] >= previous_groups[0]), + self.assertGreaterEqual(int(groups[0]), int(previous_groups[0]), "Non-monotonic seconds: '%s' before '%s'" % (previous_groups[0], groups[0])) - self.assertTrue(int(groups[1] >= previous_groups[1]) or - groups[0] != groups[1], - "Non-monotonic milliseconds: '%s' before '%s'" % - (previous_groups[1], groups[1])) + if int(groups[0]) == int(previous_groups[0]): + self.assertGreaterEqual(int(groups[1]), int(previous_groups[1]), + "Non-monotonic milliseconds: '%s' before '%s'" % + (previous_groups[1], groups[1])) self.assertEqual(int(groups[2]), pid, "Process ID mismatch: '%s' should be '%s'" % (groups[2], pid)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -457,6 +457,9 @@ Tests ----- +- Issue #15802: Fix test logic in TestMaildir.test_create_tmp. Patch + by Serhiy Storchaka. + - Issue #15747: ZFS always returns EOPNOTSUPP when attempting to set the UF_IMMUTABLE flag (via either chflags or lchflags); refactor affected tests in test_posix.py to account for this. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 13:30:47 2012 From: python-checkins at python.org (petri.lehtinen) Date: Sat, 1 Sep 2012 13:30:47 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE1ODAyOiBGaXgg?= =?utf-8?q?test_logic_in_TestMaildir=2Etest=5Fcreate=5Ftmp?= Message-ID: <3X8FcR6N30zQQb@mail.python.org> http://hg.python.org/cpython/rev/2370e331241b changeset: 78826:2370e331241b branch: 2.7 parent: 78824:a1884b3027c5 user: Petri Lehtinen date: Sat Sep 01 14:25:48 2012 +0300 summary: #15802: Fix test logic in TestMaildir.test_create_tmp files: Lib/test/test_mailbox.py | 10 +++++----- Misc/NEWS | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -660,13 +660,13 @@ self.assertTrue(match is not None, "Invalid file name: '%s'" % tail) groups = match.groups() if previous_groups is not None: - self.assertTrue(int(groups[0] >= previous_groups[0]), + self.assertGreaterEqual(int(groups[0]), int(previous_groups[0]), "Non-monotonic seconds: '%s' before '%s'" % (previous_groups[0], groups[0])) - self.assertTrue(int(groups[1] >= previous_groups[1]) or - groups[0] != groups[1], - "Non-monotonic milliseconds: '%s' before '%s'" % - (previous_groups[1], groups[1])) + if int(groups[0]) == int(previous_groups[0]): + self.assertGreaterEqual(int(groups[1]), int(previous_groups[1]), + "Non-monotonic milliseconds: '%s' before '%s'" % + (previous_groups[1], groups[1])) self.assertTrue(int(groups[2]) == pid, "Process ID mismatch: '%s' should be '%s'" % (groups[2], pid)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -352,6 +352,9 @@ Tests ----- +- Issue #15802: Fix test logic in TestMaildir.test_create_tmp. Patch + by Serhiy Storchaka. + - Issue #15765: Extend a previous fix to Solaris and OpenBSD for quirky getcwd() behaviour (issue #9185) to NetBSD as well. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 13:30:49 2012 From: python-checkins at python.org (petri.lehtinen) Date: Sat, 1 Sep 2012 13:30:49 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_=2315802=3A_Fix_test_logic_in_TestMaildir=2Etest=5Fcreat?= =?utf-8?q?e=5Ftmp?= Message-ID: <3X8FcT2h3WzQP1@mail.python.org> http://hg.python.org/cpython/rev/e2fec0144bf8 changeset: 78827:e2fec0144bf8 parent: 78822:74f6d87cd471 parent: 78825:aef4a2ba3210 user: Petri Lehtinen date: Sat Sep 01 14:27:24 2012 +0300 summary: #15802: Fix test logic in TestMaildir.test_create_tmp files: Lib/test/test_mailbox.py | 10 +++++----- Misc/NEWS | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py --- a/Lib/test/test_mailbox.py +++ b/Lib/test/test_mailbox.py @@ -763,13 +763,13 @@ self.assertIsNot(match, None, "Invalid file name: '%s'" % tail) groups = match.groups() if previous_groups is not None: - self.assertTrue(int(groups[0] >= previous_groups[0]), + self.assertGreaterEqual(int(groups[0]), int(previous_groups[0]), "Non-monotonic seconds: '%s' before '%s'" % (previous_groups[0], groups[0])) - self.assertTrue(int(groups[1] >= previous_groups[1]) or - groups[0] != groups[1], - "Non-monotonic milliseconds: '%s' before '%s'" % - (previous_groups[1], groups[1])) + if int(groups[0]) == int(previous_groups[0]): + self.assertGreaterEqual(int(groups[1]), int(previous_groups[1]), + "Non-monotonic milliseconds: '%s' before '%s'" % + (previous_groups[1], groups[1])) self.assertEqual(int(groups[2]), pid, "Process ID mismatch: '%s' should be '%s'" % (groups[2], pid)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,9 @@ Tests ----- +- Issue #15802: Fix test logic in TestMaildir.test_create_tmp. Patch + by Serhiy Storchaka. + Build ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 14:27:06 2012 From: python-checkins at python.org (stefan.krah) Date: Sat, 1 Sep 2012 14:27:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Compile_=5Fdecimal_without?= =?utf-8?q?_asserts_and_update_benchmark_results=2E?= Message-ID: <3X8GsQ1HK3zQQX@mail.python.org> http://hg.python.org/cpython/rev/259450a161ef changeset: 78828:259450a161ef user: Stefan Krah date: Sat Sep 01 14:21:22 2012 +0200 summary: Compile _decimal without asserts and update benchmark results. files: Doc/whatsnew/3.3.rst | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1119,7 +1119,7 @@ +---------+-------------+--------------+-------------+ | | decimal.py | _decimal | speedup | +=========+=============+==============+=============+ - | pi | 38.89s | 0.38s | 100x | + | pi | 42.02 | 0.345 | 120x | +---------+-------------+--------------+-------------+ | telco | 172.19s | 5.68s | 30x | +---------+-------------+--------------+-------------+ diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1897,7 +1897,7 @@ def _decimal_ext(self): extra_compile_args = [] - undef_macros = ['NDEBUG'] + undef_macros = [] if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"): include_dirs = [] libraries = ['mpdec'] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 14:33:12 2012 From: python-checkins at python.org (stefan.krah) Date: Sat, 1 Sep 2012 14:33:12 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_missing_unit=2E?= Message-ID: <3X8H0S6q4szQMt@mail.python.org> http://hg.python.org/cpython/rev/d6ebd5d28c76 changeset: 78829:d6ebd5d28c76 user: Stefan Krah date: Sat Sep 01 14:27:51 2012 +0200 summary: Add missing unit. files: Doc/whatsnew/3.3.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1119,7 +1119,7 @@ +---------+-------------+--------------+-------------+ | | decimal.py | _decimal | speedup | +=========+=============+==============+=============+ - | pi | 42.02 | 0.345 | 120x | + | pi | 42.02s | 0.345s | 120x | +---------+-------------+--------------+-------------+ | telco | 172.19s | 5.68s | 30x | +---------+-------------+--------------+-------------+ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 14:40:19 2012 From: python-checkins at python.org (stefan.krah) Date: Sat, 1 Sep 2012 14:40:19 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315814=3A_Document?= =?utf-8?q?_planned_restrictions_for_memoryview_hashes_in_3=2E3=2E1=2E?= Message-ID: <3X8H8g2PqgzQNh@mail.python.org> http://hg.python.org/cpython/rev/895e123d9476 changeset: 78830:895e123d9476 user: Stefan Krah date: Sat Sep 01 14:34:45 2012 +0200 summary: Issue #15814: Document planned restrictions for memoryview hashes in 3.3.1. files: Doc/library/stdtypes.rst | 24 ++++++++---------------- 1 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2376,8 +2376,8 @@ >>> data bytearray(b'z1spam') - Memoryviews of hashable (read-only) types are also hashable. The hash - is defined as ``hash(m) == hash(m.tobytes())``:: + Memoryviews of hashable (read-only) types with formats 'B', 'b' or 'c' + are also hashable. The hash is defined as ``hash(m) == hash(m.tobytes())``:: >>> v = memoryview(b'abcefg') >>> hash(v) == hash(b'abcefg') @@ -2387,21 +2387,13 @@ >>> hash(v[::-2]) == hash(b'abcefg'[::-2]) True - Hashing of multi-dimensional objects is supported:: - - >>> buf = bytes(list(range(12))) - >>> x = memoryview(buf) - >>> y = x.cast('B', shape=[2,2,3]) - >>> x.tolist() - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] - >>> y.tolist() - [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]] - >>> hash(x) == hash(y) == hash(y.tobytes()) - True - .. versionchanged:: 3.3 - Memoryview objects are now hashable. - + Memoryview objects with formats 'B', 'b' or 'c' are now hashable. + + .. note:: + Hashing of memoryviews with formats other than 'B', 'b' or 'c' is + possible in version 3.3.0, but will raise an error in 3.3.1 in order + to be compatible with the new memoryview equality definition. :class:`memoryview` has several methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 1 15:08:57 2012 From: python-checkins at python.org (victor.stinner) Date: Sat, 1 Sep 2012 15:08:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2314223=3A_Fix_wind?= =?utf-8?q?ow=2Eaddch=28curses=2EACS=5FHLINE=29?= Message-ID: <3X8Hnj38dRzQQK@mail.python.org> http://hg.python.org/cpython/rev/27b5bd5f0e4c changeset: 78831:27b5bd5f0e4c user: Victor Stinner date: Sat Sep 01 15:00:34 2012 +0200 summary: Close #14223: Fix window.addch(curses.ACS_HLINE) Fix window.addch() of the curses module for special characters like curses.ACS_HLINE: the Python function addch(int) and addch(bytes) is now calling the C function waddch()/mvwaddch() (as it was done in Python 3.2), instead of wadd_wch()/mvwadd_wch(). The Python function addch(str) is still calling the C function wadd_wch()/mvwadd_wch() if the Python curses is linked to libncursesw. files: Misc/NEWS | 7 +++++ Modules/_cursesmodule.c | 34 +++++----------------------- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -73,6 +73,13 @@ always returning an integer. So it is now possible to distinguish special keys like keypad keys. +- Issue #14223: Fix window.addch() of the curses module for special characters + like curses.ACS_HLINE: the Python function addch(int) and addch(bytes) is now + calling the C function waddch()/mvwaddch() (as it was done in Python 3.2), + instead of wadd_wch()/mvwadd_wch(). The Python function addch(str) is still + calling the C function wadd_wch()/mvwadd_wch() if the Python curses is linked + to libncursesw. + What's New in Python 3.3.0 Release Candidate 1? =============================================== diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -280,7 +280,6 @@ #endif ) { - int ret = 0; long value; #ifdef HAVE_NCURSESW wchar_t buffer[2]; @@ -304,7 +303,6 @@ } else if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) { value = (unsigned char)PyBytes_AsString(obj)[0]; - ret = 1; } else if (PyLong_CheckExact(obj)) { int overflow; @@ -314,11 +312,6 @@ "int doesn't fit in long"); return 0; } -#ifdef HAVE_NCURSESW - ret = 2; -#else - ret = 1; -#endif } else { PyErr_Format(PyExc_TypeError, @@ -326,27 +319,14 @@ Py_TYPE(obj)->tp_name); return 0; } -#ifdef HAVE_NCURSESW - if (ret == 2) { - memset(wch->chars, 0, sizeof(wch->chars)); - wch->chars[0] = (wchar_t)value; - if ((long)wch->chars[0] != value) { - PyErr_Format(PyExc_OverflowError, - "character doesn't fit in wchar_t"); - return 0; - } + + *ch = (chtype)value; + if ((long)*ch != value) { + PyErr_Format(PyExc_OverflowError, + "byte doesn't fit in chtype"); + return 0; } - else -#endif - { - *ch = (chtype)value; - if ((long)*ch != value) { - PyErr_Format(PyExc_OverflowError, - "byte doesn't fit in chtype"); - return 0; - } - } - return ret; + return 1; } /* Convert an object to a byte string (char*) or a wide character string -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 05:04:46 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 05:04:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Make_super=28=29_internal_?= =?utf-8?q?errors_RuntimeError_instead_of_SystemError_=28closes_=2315839?= =?utf-8?q?=29?= Message-ID: <3X8fL65svYzQ8t@mail.python.org> http://hg.python.org/cpython/rev/e2e4a0a49d2e changeset: 78832:e2e4a0a49d2e user: Benjamin Peterson date: Sat Sep 01 23:04:38 2012 -0400 summary: Make super() internal errors RuntimeError instead of SystemError (closes #15839) files: Lib/test/test_super.py | 15 +++++++++++++++ Misc/NEWS | 2 ++ Objects/typeobject.c | 14 +++++++------- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_super.py b/Lib/test/test_super.py --- a/Lib/test/test_super.py +++ b/Lib/test/test_super.py @@ -115,6 +115,21 @@ return __class__ self.assertIs(X.f(), X) + def test_obscure_super_errors(self): + def f(): + super() + self.assertRaises(RuntimeError, f) + def f(x): + del x + super() + self.assertRaises(RuntimeError, f, None) + class X: + def f(x): + nonlocal __class__ + del __class__ + super() + self.assertRaises(RuntimeError, X().f) + def test_main(): support.run_unittest(TestSuper) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #15839: Convert SystemErrors in super() to RuntimeErrors. + - Issue #15801: Make sure mappings passed to '%' formatting are actually subscriptable. diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -6497,18 +6497,18 @@ PyCodeObject *co = f->f_code; Py_ssize_t i, n; if (co == NULL) { - PyErr_SetString(PyExc_SystemError, + PyErr_SetString(PyExc_RuntimeError, "super(): no code object"); return -1; } if (co->co_argcount == 0) { - PyErr_SetString(PyExc_SystemError, + PyErr_SetString(PyExc_RuntimeError, "super(): no arguments"); return -1; } obj = f->f_localsplus[0]; if (obj == NULL) { - PyErr_SetString(PyExc_SystemError, + PyErr_SetString(PyExc_RuntimeError, "super(): arg[0] deleted"); return -1; } @@ -6527,18 +6527,18 @@ PyTuple_GET_SIZE(co->co_cellvars) + i; PyObject *cell = f->f_localsplus[index]; if (cell == NULL || !PyCell_Check(cell)) { - PyErr_SetString(PyExc_SystemError, + PyErr_SetString(PyExc_RuntimeError, "super(): bad __class__ cell"); return -1; } type = (PyTypeObject *) PyCell_GET(cell); if (type == NULL) { - PyErr_SetString(PyExc_SystemError, + PyErr_SetString(PyExc_RuntimeError, "super(): empty __class__ cell"); return -1; } if (!PyType_Check(type)) { - PyErr_Format(PyExc_SystemError, + PyErr_Format(PyExc_RuntimeError, "super(): __class__ is not a type (%s)", Py_TYPE(type)->tp_name); return -1; @@ -6547,7 +6547,7 @@ } } if (type == NULL) { - PyErr_SetString(PyExc_SystemError, + PyErr_SetString(PyExc_RuntimeError, "super(): __class__ cell not found"); return -1; } -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Sep 2 05:58:19 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 02 Sep 2012 05:58:19 +0200 Subject: [Python-checkins] Daily reference leaks (27b5bd5f0e4c): sum=0 Message-ID: results for 27b5bd5f0e4c on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog0U4FpJ', '-x'] From python-checkins at python.org Sun Sep 2 14:57:20 2012 From: python-checkins at python.org (stefan.krah) Date: Sun, 2 Sep 2012 14:57:20 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315814=3A_Document?= =?utf-8?q?ation=3A_disallow_hashing_of_multi-dimensional_memoryviews=2E?= Message-ID: <3X8vTr3Hx1zQW7@mail.python.org> http://hg.python.org/cpython/rev/3b2597c1fe35 changeset: 78833:3b2597c1fe35 user: Stefan Krah date: Sun Sep 02 14:50:56 2012 +0200 summary: Issue #15814: Documentation: disallow hashing of multi-dimensional memoryviews. files: Doc/library/stdtypes.rst | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2376,8 +2376,9 @@ >>> data bytearray(b'z1spam') - Memoryviews of hashable (read-only) types with formats 'B', 'b' or 'c' - are also hashable. The hash is defined as ``hash(m) == hash(m.tobytes())``:: + One-dimensional memoryviews of hashable (read-only) types with formats + 'B', 'b' or 'c' are also hashable. The hash is defined as + ``hash(m) == hash(m.tobytes())``:: >>> v = memoryview(b'abcefg') >>> hash(v) == hash(b'abcefg') @@ -2388,12 +2389,13 @@ True .. versionchanged:: 3.3 - Memoryview objects with formats 'B', 'b' or 'c' are now hashable. + One-dimensional memoryviews with formats 'B', 'b' or 'c' are now hashable. .. note:: - Hashing of memoryviews with formats other than 'B', 'b' or 'c' is - possible in version 3.3.0, but will raise an error in 3.3.1 in order - to be compatible with the new memoryview equality definition. + Hashing of memoryviews with formats other than 'B', 'b' or 'c' as well + as hashing of multi-dimensional memoryviews is possible in version 3.3.0, + but will raise an error in 3.3.1 in order to be compatible with the new + memoryview equality definition. :class:`memoryview` has several methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 18:00:21 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 2 Sep 2012 18:00:21 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_C++-style_comment_=28x?= =?utf-8?q?lc_compilation_failure=29?= Message-ID: <3X8zY15zCmzM7H@mail.python.org> http://hg.python.org/cpython/rev/db34753bd70e changeset: 78834:db34753bd70e user: Antoine Pitrou date: Sun Sep 02 17:56:33 2012 +0200 summary: Fix C++-style comment (xlc compilation failure) files: Objects/unicodeobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9146,7 +9146,7 @@ /* We do not need to compare 0 and len(substring)-1 because the if statement above ensured already that they are equal when we end up here. */ - // TODO: honor direction and do a forward or backwards search + /* TODO: honor direction and do a forward or backwards search */ for (i = 1; i < end_sub; ++i) { if (PyUnicode_READ(kind_self, data_self, offset + i) != PyUnicode_READ(kind_sub, data_sub, i)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 20:25:25 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 20:25:25 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_prevert_ast_er?= =?utf-8?q?rors_from_being_normalized_before_ast=5Ferror=5Ffinish_is_calle?= =?utf-8?q?d?= Message-ID: <3X92mP5mdMzQLW@mail.python.org> http://hg.python.org/cpython/rev/0db75a55145a changeset: 78835:0db75a55145a branch: 3.2 parent: 78825:aef4a2ba3210 user: Benjamin Peterson date: Sun Sep 02 14:23:15 2012 -0400 summary: prevert ast errors from being normalized before ast_error_finish is called (closes #15846) files: Lib/test/test_ast.py | 6 ++++++ Misc/NEWS | 3 +++ Python/ast.c | 8 ++++++++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -386,6 +386,12 @@ b = compile('foo(1 + 1)', '', 'exec', ast.PyCF_ONLY_AST) self.assertEqual(ast.dump(a), ast.dump(b)) + def test_parse_in_error(self): + try: + 1/0 + except Exception: + self.assertRaises(SyntaxError, ast.parse, r"'\U'") + def test_dump(self): node = ast.parse('spam(eggs, "and cheese")') self.assertEqual(ast.dump(node), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #15846: Fix SystemError which happened when using ast.parse in an + exception handler on code with syntax errors. + - Issue #15761: Fix crash when PYTHONEXECUTABLE is set on Mac OS X. - Issue #15801: Make sure mappings passed to '%' formatting are actually diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -92,7 +92,15 @@ PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset); if (!u) return 0; + /* + * Prevent the error from being chained. PyErr_SetObject will normalize the + * exception in order to chain it. ast_error_finish, however, requires the + * error not to be normalized. + */ + PyObject *save = PyThreadState_GET()->exc_value; + PyThreadState_GET()->exc_value = NULL; PyErr_SetObject(PyExc_SyntaxError, u); + PyThreadState_GET()->exc_value = save; Py_DECREF(u); return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 20:25:27 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 20:25:27 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4yICgjMTU4NDYp?= Message-ID: <3X92mR2XJrzQ1g@mail.python.org> http://hg.python.org/cpython/rev/d61424122af5 changeset: 78836:d61424122af5 parent: 78833:3b2597c1fe35 parent: 78835:0db75a55145a user: Benjamin Peterson date: Sun Sep 02 14:24:44 2012 -0400 summary: merge 3.2 (#15846) files: Lib/test/test_ast.py | 6 ++++++ Misc/NEWS | 3 +++ Python/ast.c | 8 ++++++++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -407,6 +407,12 @@ b = compile('foo(1 + 1)', '', 'exec', ast.PyCF_ONLY_AST) self.assertEqual(ast.dump(a), ast.dump(b)) + def test_parse_in_error(self): + try: + 1/0 + except Exception: + self.assertRaises(SyntaxError, ast.parse, r"'\U'") + def test_dump(self): node = ast.parse('spam(eggs, "and cheese")') self.assertEqual(ast.dump(node), diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ - Issue #15839: Convert SystemErrors in super() to RuntimeErrors. +- Issue #15846: Fix SystemError which happened when using ast.parse in an + exception handler on code with syntax errors. + - Issue #15801: Make sure mappings passed to '%' formatting are actually subscriptable. diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -588,7 +588,15 @@ PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset); if (!u) return 0; + /* + * Prevent the error from being chained. PyErr_SetObject will normalize the + * exception in order to chain it. ast_error_finish, however, requires the + * error not to be normalized. + */ + PyObject *save = PyThreadState_GET()->exc_value; + PyThreadState_GET()->exc_value = NULL; PyErr_SetObject(PyExc_SyntaxError, u); + PyThreadState_GET()->exc_value = save; Py_DECREF(u); return 0; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 20:25:29 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 20:25:29 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <3X92mT2b2LzNhM@mail.python.org> http://hg.python.org/cpython/rev/a2294412d214 changeset: 78837:a2294412d214 parent: 78836:d61424122af5 parent: 78834:db34753bd70e user: Benjamin Peterson date: Sun Sep 02 14:25:18 2012 -0400 summary: merge heads files: Objects/unicodeobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -9146,7 +9146,7 @@ /* We do not need to compare 0 and len(substring)-1 because the if statement above ensured already that they are equal when we end up here. */ - // TODO: honor direction and do a forward or backwards search + /* TODO: honor direction and do a forward or backwards search */ for (i = 1; i < end_sub; ++i) { if (PyUnicode_READ(kind_self, data_self, offset + i) != PyUnicode_READ(kind_sub, data_sub, i)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 20:38:20 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 20:38:20 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_move_variable_?= =?utf-8?q?decl_to_the_top_of_the_function?= Message-ID: <3X933J1q7rzQVX@mail.python.org> http://hg.python.org/cpython/rev/a5e28f9924c3 changeset: 78838:a5e28f9924c3 branch: 3.2 parent: 78835:0db75a55145a user: Benjamin Peterson date: Sun Sep 02 14:38:08 2012 -0400 summary: move variable decl to the top of the function files: Python/ast.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -89,7 +89,7 @@ static int ast_error(const node *n, const char *errstr) { - PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset); + PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset), *save; if (!u) return 0; /* @@ -97,7 +97,7 @@ * exception in order to chain it. ast_error_finish, however, requires the * error not to be normalized. */ - PyObject *save = PyThreadState_GET()->exc_value; + save = PyThreadState_GET()->exc_value; PyThreadState_GET()->exc_value = NULL; PyErr_SetObject(PyExc_SyntaxError, u); PyThreadState_GET()->exc_value = save; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 20:38:21 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 20:38:21 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4y?= Message-ID: <3X933K5XwKzQWR@mail.python.org> http://hg.python.org/cpython/rev/f96df022f124 changeset: 78839:f96df022f124 parent: 78837:a2294412d214 parent: 78838:a5e28f9924c3 user: Benjamin Peterson date: Sun Sep 02 14:38:15 2012 -0400 summary: merge 3.2 files: Python/ast.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -585,7 +585,7 @@ static int ast_error(const node *n, const char *errstr) { - PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset); + PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset), *save; if (!u) return 0; /* @@ -593,7 +593,7 @@ * exception in order to chain it. ast_error_finish, however, requires the * error not to be normalized. */ - PyObject *save = PyThreadState_GET()->exc_value; + save = PyThreadState_GET()->exc_value; PyThreadState_GET()->exc_value = NULL; PyErr_SetObject(PyExc_SyntaxError, u); PyThreadState_GET()->exc_value = save; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 21:05:04 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 21:05:04 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_get_rid_of_ast=5Ferror=5Ff?= =?utf-8?q?inish_by_passing_the_compiling_struct_to_ast=5Ferror?= Message-ID: <3X93f8541lzQPN@mail.python.org> http://hg.python.org/cpython/rev/58de275e9224 changeset: 78840:58de275e9224 user: Benjamin Peterson date: Sun Sep 02 15:04:51 2012 -0400 summary: get rid of ast_error_finish by passing the compiling struct to ast_error files: Lib/test/test_ast.py | 4 +- Python/ast.c | 190 +++++++++++------------------- 2 files changed, 75 insertions(+), 119 deletions(-) diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -411,7 +411,9 @@ try: 1/0 except Exception: - self.assertRaises(SyntaxError, ast.parse, r"'\U'") + with self.assertRaises(SyntaxError) as e: + ast.literal_eval(r"'\U'") + self.assertIsNotNone(e.exception.__context__) def test_dump(self): node = ast.parse('spam(eggs, "and cheese")') diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -574,87 +574,43 @@ #define NEW_IDENTIFIER(n) new_identifier(STR(n), c) -/* This routine provides an invalid object for the syntax error. - The outermost routine must unpack this error and create the - proper object. We do this so that we don't have to pass - the filename to everything function. - - XXX Maybe we should just pass the filename... -*/ - static int -ast_error(const node *n, const char *errstr) +ast_error(struct compiling *c, const node *n, const char *errmsg) { - PyObject *u = Py_BuildValue("zii", errstr, LINENO(n), n->n_col_offset), *save; - if (!u) - return 0; - /* - * Prevent the error from being chained. PyErr_SetObject will normalize the - * exception in order to chain it. ast_error_finish, however, requires the - * error not to be normalized. - */ - save = PyThreadState_GET()->exc_value; - PyThreadState_GET()->exc_value = NULL; - PyErr_SetObject(PyExc_SyntaxError, u); - PyThreadState_GET()->exc_value = save; - Py_DECREF(u); - return 0; -} - -static void -ast_error_finish(const char *filename) -{ - PyObject *type, *value, *tback, *errstr, *offset, *loc, *tmp; + PyObject *value, *errstr, *loc, *tmp; PyObject *filename_obj; - long lineno; - - assert(PyErr_Occurred()); - if (!PyErr_ExceptionMatches(PyExc_SyntaxError)) - return; - - PyErr_Fetch(&type, &value, &tback); - errstr = PyTuple_GetItem(value, 0); - if (!errstr) - return; - Py_INCREF(errstr); - lineno = PyLong_AsLong(PyTuple_GetItem(value, 1)); - if (lineno == -1) { - Py_DECREF(errstr); - return; - } - offset = PyTuple_GetItem(value, 2); - if (!offset) { - Py_DECREF(errstr); - return; - } - Py_DECREF(value); - - loc = PyErr_ProgramText(filename, lineno); + + loc = PyErr_ProgramText(c->c_filename, LINENO(n)); if (!loc) { Py_INCREF(Py_None); loc = Py_None; } - if (filename != NULL) - filename_obj = PyUnicode_DecodeFSDefault(filename); - else { + if (c->c_filename) { + filename_obj = PyUnicode_DecodeFSDefault(c->c_filename); + if (!filename_obj) { + Py_DECREF(loc); + return 0; + } + } else { Py_INCREF(Py_None); filename_obj = Py_None; } - if (filename_obj != NULL) - tmp = Py_BuildValue("(NlOO)", filename_obj, lineno, offset, loc); - else - tmp = NULL; - Py_DECREF(loc); - if (!tmp) { - Py_DECREF(errstr); - return; + tmp = Py_BuildValue("(NiiN)", filename_obj, LINENO(n), n->n_col_offset, loc); + if (!tmp) + return 0; + errstr = PyUnicode_FromString(errmsg); + if (!errstr) { + Py_DECREF(tmp); + return 0; } value = PyTuple_Pack(2, errstr, tmp); Py_DECREF(errstr); Py_DECREF(tmp); - if (!value) - return; - PyErr_Restore(type, value, tback); + if (value) { + PyErr_SetObject(PyExc_SyntaxError, value); + Py_DECREF(value); + } + return 0; } /* num_stmts() returns number of contained statements. @@ -732,11 +688,14 @@ struct compiling c; mod_ty res = NULL; + c.c_arena = arena; + c.c_filename = filename; + c.c_normalize = c.c_normalize_args = NULL; if (flags && flags->cf_flags & PyCF_SOURCE_IS_UTF8) { c.c_encoding = "utf-8"; if (TYPE(n) == encoding_decl) { #if 0 - ast_error(n, "encoding declaration in Unicode string"); + ast_error(c, n, "encoding declaration in Unicode string"); goto out; #endif n = CHILD(n, 0); @@ -748,9 +707,6 @@ /* PEP 3120 */ c.c_encoding = "utf-8"; } - c.c_arena = arena; - c.c_filename = filename; - c.c_normalize = c.c_normalize_args = NULL; k = 0; switch (TYPE(n)) { @@ -843,8 +799,6 @@ PyTuple_SET_ITEM(c.c_normalize_args, 1, NULL); Py_DECREF(c.c_normalize_args); } - if (!res) - ast_error_finish(filename); return res; } @@ -890,18 +844,18 @@ }; static int -forbidden_name(identifier name, const node *n, int full_checks) +forbidden_name(struct compiling *c, identifier name, const node *n, int full_checks) { assert(PyUnicode_Check(name)); if (PyUnicode_CompareWithASCIIString(name, "__debug__") == 0) { - ast_error(n, "assignment to keyword"); + ast_error(c, n, "assignment to keyword"); return 1; } if (full_checks) { const char **p; for (p = FORBIDDEN; *p; p++) { if (PyUnicode_CompareWithASCIIString(name, *p) == 0) { - ast_error(n, "assignment to keyword"); + ast_error(c, n, "assignment to keyword"); return 1; } } @@ -937,7 +891,7 @@ switch (e->kind) { case Attribute_kind: e->v.Attribute.ctx = ctx; - if (ctx == Store && forbidden_name(e->v.Attribute.attr, n, 1)) + if (ctx == Store && forbidden_name(c, e->v.Attribute.attr, n, 1)) return 0; break; case Subscript_kind: @@ -950,7 +904,7 @@ break; case Name_kind: if (ctx == Store) { - if (forbidden_name(e->v.Name.id, n, 1)) + if (forbidden_name(c, e->v.Name.id, n, 1)) return 0; /* forbidden_name() calls ast_error() */ } e->v.Name.ctx = ctx; @@ -1024,7 +978,7 @@ "can't %s %s", ctx == Store ? "assign to" : "delete", expr_name); - return ast_error(n, buf); + return ast_error(c, n, buf); } /* If the LHS is a list or tuple, we need to set the assignment @@ -1172,7 +1126,7 @@ name = NEW_IDENTIFIER(ch); if (!name) return NULL; - if (forbidden_name(name, ch, 0)) + if (forbidden_name(c, name, ch, 0)) return NULL; if (NCH(n) == 3 && TYPE(CHILD(n, 1)) == COLON) { @@ -1202,7 +1156,7 @@ int j = 0; /* index for kwdefaults and kwonlyargs */ if (kwonlyargs == NULL) { - ast_error(CHILD(n, start), "named arguments must follow bare *"); + ast_error(c, CHILD(n, start), "named arguments must follow bare *"); return -1; } assert(kwdefaults != NULL); @@ -1234,7 +1188,7 @@ argname = NEW_IDENTIFIER(ch); if (!argname) goto error; - if (forbidden_name(argname, ch, 0)) + if (forbidden_name(c, argname, ch, 0)) goto error; arg = arg(argname, annotation, c->c_arena); if (!arg) @@ -1245,7 +1199,7 @@ case DOUBLESTAR: return i; default: - ast_error(ch, "unexpected node"); + ast_error(c, ch, "unexpected node"); goto error; } } @@ -1337,7 +1291,7 @@ return NULL; if (nposargs + nkwonlyargs > 255) { - ast_error(n, "more than 255 arguments"); + ast_error(c, n, "more than 255 arguments"); return NULL; } @@ -1365,7 +1319,7 @@ found_default = 1; } else if (found_default) { - ast_error(n, + ast_error(c, n, "non-default argument follows default argument"); return NULL; } @@ -1377,7 +1331,7 @@ break; case STAR: if (i+1 >= NCH(n)) { - ast_error(CHILD(n, i), + ast_error(c, CHILD(n, i), "named arguments must follow bare *"); return NULL; } @@ -1394,7 +1348,7 @@ vararg = NEW_IDENTIFIER(CHILD(ch, 0)); if (!vararg) return NULL; - if (forbidden_name(vararg, CHILD(ch, 0), 0)) + if (forbidden_name(c, vararg, CHILD(ch, 0), 0)) return NULL; if (NCH(ch) > 1) { /* there is an annotation on the vararg */ @@ -1425,7 +1379,7 @@ if (!kwargannotation) return NULL; } - if (forbidden_name(kwarg, CHILD(ch, 0), 0)) + if (forbidden_name(c, kwarg, CHILD(ch, 0), 0)) return NULL; i += 3; break; @@ -1544,7 +1498,7 @@ name = NEW_IDENTIFIER(CHILD(n, name_i)); if (!name) return NULL; - if (forbidden_name(name, CHILD(n, name_i), 0)) + if (forbidden_name(c, name, CHILD(n, name_i), 0)) return NULL; args = ast_for_arguments(c, CHILD(n, name_i + 1)); if (!args) @@ -1885,10 +1839,10 @@ char buf[128]; s = _PyUnicode_AsString(errstr); PyOS_snprintf(buf, sizeof(buf), "(unicode error) %s", s); - ast_error(n, buf); + ast_error(c, n, buf); Py_DECREF(errstr); } else { - ast_error(n, "(unicode error) unknown error"); + ast_error(c, n, "(unicode error) unknown error"); } Py_DECREF(type); Py_DECREF(value); @@ -2473,14 +2427,14 @@ } } if (ngens > 1 || (ngens && (nargs || nkeywords))) { - ast_error(n, "Generator expression must be parenthesized " + ast_error(c, n, "Generator expression must be parenthesized " "if not sole argument"); return NULL; } if (nargs + nkeywords + ngens > 255) { - ast_error(n, "more than 255 arguments"); - return NULL; + ast_error(c, n, "more than 255 arguments"); + return NULL; } args = asdl_seq_new(nargs + ngens, c->c_arena); @@ -2497,12 +2451,12 @@ expr_ty e; if (NCH(ch) == 1) { if (nkeywords) { - ast_error(CHILD(ch, 0), + ast_error(c, CHILD(ch, 0), "non-keyword arg after keyword arg"); return NULL; } if (vararg) { - ast_error(CHILD(ch, 0), + ast_error(c, CHILD(ch, 0), "only named arguments may follow *expression"); return NULL; } @@ -2532,19 +2486,19 @@ * then is very confusing. */ if (e->kind == Lambda_kind) { - ast_error(CHILD(ch, 0), "lambda cannot contain assignment"); + ast_error(c, CHILD(ch, 0), "lambda cannot contain assignment"); return NULL; } else if (e->kind != Name_kind) { - ast_error(CHILD(ch, 0), "keyword can't be an expression"); + ast_error(c, CHILD(ch, 0), "keyword can't be an expression"); return NULL; - } else if (forbidden_name(e->v.Name.id, ch, 1)) { + } else if (forbidden_name(c, e->v.Name.id, ch, 1)) { return NULL; } key = e->v.Name.id; for (k = 0; k < nkeywords; k++) { tmp = ((keyword_ty)asdl_seq_GET(keywords, k))->arg; if (!PyUnicode_Compare(tmp, key)) { - ast_error(CHILD(ch, 0), "keyword argument repeated"); + ast_error(c, CHILD(ch, 0), "keyword argument repeated"); return NULL; } } @@ -2637,7 +2591,7 @@ case Subscript_kind: break; default: - ast_error(ch, "illegal expression for augmented assignment"); + ast_error(c, ch, "illegal expression for augmented assignment"); return NULL; } @@ -2670,7 +2624,7 @@ expr_ty e; node *ch = CHILD(n, i); if (TYPE(ch) == yield_expr) { - ast_error(ch, "assignment to yield expression not possible"); + ast_error(c, ch, "assignment to yield expression not possible"); return NULL; } e = ast_for_testlist(c, ch); @@ -2817,11 +2771,11 @@ str = NEW_IDENTIFIER(str_node); if (!str) return NULL; - if (store && forbidden_name(str, str_node, 0)) + if (store && forbidden_name(c, str, str_node, 0)) return NULL; } else { - if (forbidden_name(name, name_node, 0)) + if (forbidden_name(c, name, name_node, 0)) return NULL; } return alias(name, str, c->c_arena); @@ -2840,7 +2794,7 @@ a->asname = NEW_IDENTIFIER(asname_node); if (!a->asname) return NULL; - if (forbidden_name(a->asname, asname_node, 0)) + if (forbidden_name(c, a->asname, asname_node, 0)) return NULL; return a; } @@ -2851,7 +2805,7 @@ name = NEW_IDENTIFIER(name_node); if (!name) return NULL; - if (store && forbidden_name(name, name_node, 0)) + if (store && forbidden_name(c, name, name_node, 0)) return NULL; return alias(name, NULL, c->c_arena); } @@ -2980,13 +2934,13 @@ n = CHILD(n, idx); n_children = NCH(n); if (n_children % 2 == 0) { - ast_error(n, "trailing comma not allowed without" + ast_error(c, n, "trailing comma not allowed without" " surrounding parentheses"); return NULL; } break; default: - ast_error(n, "Unexpected node-type in from-import"); + ast_error(c, n, "Unexpected node-type in from-import"); return NULL; } @@ -3392,7 +3346,7 @@ identifier e = NEW_IDENTIFIER(CHILD(exc, 3)); if (!e) return NULL; - if (forbidden_name(e, CHILD(exc, 3), 0)) + if (forbidden_name(c, e, CHILD(exc, 3), 0)) return NULL; expression = ast_for_expr(c, CHILD(exc, 1)); if (!expression) @@ -3451,7 +3405,7 @@ } } else if (TYPE(CHILD(n, nch - 3)) != except_clause) { - ast_error(n, "malformed 'try' statement"); + ast_error(c, n, "malformed 'try' statement"); return NULL; } @@ -3543,7 +3497,7 @@ classname = NEW_IDENTIFIER(CHILD(n, 1)); if (!classname) return NULL; - if (forbidden_name(classname, CHILD(n, 3), 0)) + if (forbidden_name(c, classname, CHILD(n, 3), 0)) return NULL; return ClassDef(classname, NULL, NULL, NULL, NULL, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); @@ -3556,7 +3510,7 @@ classname = NEW_IDENTIFIER(CHILD(n, 1)); if (!classname) return NULL; - if (forbidden_name(classname, CHILD(n, 3), 0)) + if (forbidden_name(c, classname, CHILD(n, 3), 0)) return NULL; return ClassDef(classname, NULL, NULL, NULL, NULL, s, decorator_seq, LINENO(n), n->n_col_offset, c->c_arena); @@ -3581,7 +3535,7 @@ classname = NEW_IDENTIFIER(CHILD(n, 1)); if (!classname) return NULL; - if (forbidden_name(classname, CHILD(n, 1), 0)) + if (forbidden_name(c, classname, CHILD(n, 1), 0)) return NULL; return ClassDef(classname, call->v.Call.args, call->v.Call.keywords, @@ -3840,10 +3794,10 @@ } if (*bytesmode) { /* Disallow non-ascii characters (but not escapes) */ - const char *c; - for (c = s; *c; c++) { - if (Py_CHARMASK(*c) >= 0x80) { - ast_error(n, "bytes can only contain ASCII " + const char *ch; + for (ch = s; *ch; ch++) { + if (Py_CHARMASK(*ch) >= 0x80) { + ast_error(c, n, "bytes can only contain ASCII " "literal characters."); return NULL; } @@ -3891,7 +3845,7 @@ if (s == NULL) goto onError; if (*bytesmode != subbm) { - ast_error(n, "cannot mix bytes and nonbytes literals"); + ast_error(c, n, "cannot mix bytes and nonbytes literals"); goto onError; } if (PyBytes_Check(v) && PyBytes_Check(s)) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 22:37:17 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 22:37:17 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_put_*_in_the_n?= =?utf-8?q?ormal_place?= Message-ID: <3X95hY4T0JzQCP@mail.python.org> http://hg.python.org/cpython/rev/0c6a09b982d8 changeset: 78841:0c6a09b982d8 branch: 3.2 parent: 78838:a5e28f9924c3 user: Benjamin Peterson date: Sun Sep 02 16:36:01 2012 -0400 summary: put * in the normal place files: Python/ast.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -47,9 +47,9 @@ #define COMP_SETCOMP 2 static identifier -new_identifier(const char* n, PyArena *arena) +new_identifier(const char *n, PyArena *arena) { - PyObject* id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); + PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); Py_UNICODE *u; if (!id) return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 2 22:37:19 2012 From: python-checkins at python.org (benjamin.peterson) Date: Sun, 2 Sep 2012 22:37:19 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4y?= Message-ID: <3X95hb1pDBzQDt@mail.python.org> http://hg.python.org/cpython/rev/8ff2f4634ed8 changeset: 78842:8ff2f4634ed8 parent: 78840:58de275e9224 parent: 78841:0c6a09b982d8 user: Benjamin Peterson date: Sun Sep 02 16:37:09 2012 -0400 summary: merge 3.2 files: Python/ast.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -545,9 +545,9 @@ } static identifier -new_identifier(const char* n, struct compiling *c) +new_identifier(const char *n, struct compiling *c) { - PyObject* id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); + PyObject *id = PyUnicode_DecodeUTF8(n, strlen(n), NULL); if (!id) return NULL; /* PyUnicode_DecodeUTF8 should always return a ready string. */ -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Sep 3 06:03:07 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 03 Sep 2012 06:03:07 +0200 Subject: [Python-checkins] Daily reference leaks (8ff2f4634ed8): sum=0 Message-ID: results for 8ff2f4634ed8 on branch "default" -------------------------------------------- test_support leaked [-1, 1, 0] references, sum=0 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogpRmYOX', '-x'] From python-checkins at python.org Mon Sep 3 13:19:36 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 3 Sep 2012 13:19:36 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Explicitly_recast_this_propos?= =?utf-8?q?al_as_a_new_kind_of_decorator_clause?= Message-ID: <3X9TGc4mpxzQJm@mail.python.org> http://hg.python.org/peps/rev/ba7a581514d0 changeset: 4503:ba7a581514d0 user: Nick Coghlan date: Mon Sep 03 21:19:27 2012 +1000 summary: Explicitly recast this proposal as a new kind of decorator clause files: pep-0403.txt | 129 ++++++++++++++++++++++++++------------ 1 files changed, 88 insertions(+), 41 deletions(-) diff --git a/pep-0403.txt b/pep-0403.txt --- a/pep-0403.txt +++ b/pep-0403.txt @@ -1,5 +1,5 @@ PEP: 403 -Title: Statement local functions and classes +Title: General purpose decorator clause Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan @@ -15,17 +15,18 @@ Abstract ======== -This PEP proposes the addition of a new ``in`` statement that accepts a -statement local function or class definition. +This PEP proposes the addition of a new ``@in`` decorator clause that makes +it possible to override the name binding step of a function or class +definition. -The statement accepts a single simple statement that can make a forward -reference to a trailing function or class definition. +The new clause accepts a single simple statement that can make a forward +reference to decorated function or class definition. -This new statement is designed to be used whenever a "one-shot" function or +This new clause is designed to be used whenever a "one-shot" function or class is needed, and placing the function or class definition before the statement that uses it actually makes the code harder to read. It also avoids any name shadowing concerns by making sure the new name is visible -only to the statement in the ``in`` clause. +only to the statement in the ``@in`` clause. This PEP is based heavily on many of the ideas in PEP 3150 (Statement Local Namespaces) so some elements of the rationale will be familiar to readers of @@ -41,7 +42,7 @@ As a trivial example, a weakref callback could be defined as follows:: - in x = weakref.ref(target, report_destruction) + @in x = weakref.ref(target, report_destruction) def report_destruction(obj): print("{} is being destroyed".format(obj)) @@ -59,7 +60,7 @@ If the repetition of the name seems especially annoying, then a throwaway name like ``f`` can be used instead:: - in x = weakref.ref(target, f) + @in x = weakref.ref(target, f) def f(obj): print("{} is being destroyed".format(obj)) @@ -67,7 +68,7 @@ Similarly, a sorted operation on a particularly poorly defined type could now be defined as:: - in sorted_list = sorted(original, key=f) + @in sorted_list = sorted(original, key=f) def f(item): try: return item.calc_sort_order() @@ -86,7 +87,7 @@ And early binding semantics in a list comprehension could be attained via:: - in funcs = [adder(i) for i in range(10)] + @in funcs = [adder(i) for i in range(10)] def adder(i): return lambda x: x + i @@ -94,34 +95,50 @@ Proposal ======== -This PEP proposes the addition of a new ``in`` statement that is a variant -of the existing class and function definition syntax. +This PEP proposes the addition of a new ``@in`` clause that is a variant +of the existing class and function decorator syntax. -The new ``in`` clause replaces the decorator lines, and allows forward +The new ``@in`` clause precedes the decorator lines, and allows forward references to the trailing function or class definition. The trailing function or class definition is always named - the name of the trailing definition is then used to make the forward reference from the -preceding statement. +``@in`` clause. -The ``in`` clause is allowed to contain any simple statement (including those -that don't make any sense in that context, such as ``pass`` - while such code -would be legal, there wouldn't be any point in writing it). This permissive -structure is easier to define and easier to explain, but a more restrictive -approach that only permits operations that "make sense" would also be -possible (see PEP 3150 for a list of possible candidates). +The ``@in`` clause is allowed to contain any simple statement (including +those that don't make any sense in that context, such as ``pass`` - while +such code would be legal, there wouldn't be any point in writing it). This +permissive structure is easier to define and easier to explain, but a more +restrictive approach that only permits operations that "make sense" would +also be possible (see PEP 3150 for a list of possible candidates). -The ``in`` statement will not create a new scope - all name binding +The ``@in`` clause will not create a new scope - all name binding operations aside from the trailing function or class definition will affect the containing scope. The name used in the trailing function or class definition is only visible -from the associated ``in`` clause, and behaves as if it was an ordinary +from the associated ``@in`` clause, and behaves as if it was an ordinary variable defined in that scope. If any nested scopes are created in either -the ``in`` clause or the trailing function or class definition, those scopes +the ``@in`` clause or the trailing function or class definition, those scopes will see the trailing function or class definition rather than any other bindings for that name in the containing scope. +In a very real sense, this proposal is about making it possible to override +the implicit "name = " name binding operation +that is part of every function or class definition, specifically in those +cases where the local name binding isn't actually needed. + +Under this PEP, an ordinary class or function definition:: + + def name(): + ... + +would be equivalent to:: + + @in name = name + def name(): + ... + Background ========== @@ -147,7 +164,7 @@ * comprehensions, generator expressions, map(), filter() * key arguments to sorted(), min(), max() * partial function application - * provision of callbacks (e.g. for weak references) + * provision of callbacks (e.g. for weak references or aysnchronous IO) * array broadcast operations in NumPy However, adopting Ruby's block syntax directly won't work for Python, since @@ -197,6 +214,11 @@ The ``in`` keyword was chosen as an existing keyword that can be used to denote the concept of a forward reference. +The ``@`` prefix was included in order to exploit the fact that Python +programmers are already used to decorator syntax as an indication of +out of order execution, where the function or class is actually defined +*first* and then decorators are applied in reverse order. + For functions, the construct is intended to be read as "in define NAME as a function that does ". @@ -231,9 +253,9 @@ Syntax Change ============= -New:: +Syntactically, only one new grammar rule is needed:: - in_stmt: 'in' simple_stmt (classdef|funcdef) + in_stmt: '@in' simple_stmt decorated Grammar: http://hg.python.org/cpython/file/default/Grammar/Grammar @@ -244,10 +266,10 @@ This proposal has at least one titanic advantage over PEP 3150: implementation should be relatively straightforward. -The AST for the ``in`` statement will include both the function or class -definition and the statement that references it, so it should just be a -matter of emitting the two operations out of order and using a hidden -variable to link up any references. +The ``@in`` clause will be included in the AST for the associated function or +class definition and the statement that references it. When the ``@in`` +clause is present, it will be emitted in place of the local name binding +operation normally implied by a function or class definition. The one potentially tricky part is changing the meaning of the references to the statement local function or namespace while within the scope of the @@ -268,7 +290,7 @@ del _createenviron # Becomes: - in environ = _createenviron() + @in environ = _createenviron() def _createenviron(): ... # 27 line function @@ -278,25 +300,45 @@ funcs = [(lambda x, i=i: x + i) for i in range(10)] # Becomes: - in funcs = [adder(i) for i in range(10)] + @in funcs = [adder(i) for i in range(10)] def adder(i): - return lambda x: x + i + return lambda x: x + i # Or even: - in funcs = [adder(i) for i in range(10)] + @in funcs = [adder(i) for i in range(10)] def adder(i): - in return incr - def incr(x): - return x + i + @in return incr + def incr(x): + return x + i A trailing class can be used as a statement local namespace:: # Evaluate subexpressions only once - in c = math.sqrt(x.a*x.a + x.b*x.b) + @in c = math.sqrt(x.a*x.a + x.b*x.b) class x: - a = calculate_a() - b = calculate_b() + a = calculate_a() + b = calculate_b() +A function can be bound directly to a location which isn't a valid +identifier:: + + @in dispatch[MyClass] = f + def f(): + ... + +Constructs that verge on decorator abuse can be eliminated:: + + # Current Python + @call + def f(): + ... + + # Becomes: + @in f() + def f(): + ... + + Reference Implementation ======================== @@ -335,6 +377,11 @@ a = calculate_a() b = calculate_b() +Another past alternative omitted the ``@`` prefix. However, without that +prefix, the bare ``in`` keyword didn't associate the clause strongly +enough with the subsequent function or class definition. Reusing the +decorator prefix and explicitly characterising the new construct as a kind +of decorator clause should address that problem. References ========== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Sep 3 13:33:26 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 3 Sep 2012 13:33:26 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Don=27t_have_quite_so_many_to?= =?utf-8?q?p_level_headings?= Message-ID: <3X9TZZ01C1zPpX@mail.python.org> http://hg.python.org/peps/rev/4ad4bea85935 changeset: 4504:4ad4bea85935 user: Nick Coghlan date: Mon Sep 03 21:33:16 2012 +1000 summary: Don't have quite so many top level headings files: pep-0403.txt | 37 ++++++++++++++++++++----------------- 1 files changed, 20 insertions(+), 17 deletions(-) diff --git a/pep-0403.txt b/pep-0403.txt --- a/pep-0403.txt +++ b/pep-0403.txt @@ -139,9 +139,21 @@ def name(): ... +Syntax Change +------------- + +Syntactically, only one new grammar rule is needed:: + + in_stmt: '@in' simple_stmt decorated + +Grammar: http://hg.python.org/cpython/file/default/Grammar/Grammar + + +Design Discussion +================= Background -========== +---------- The question of "multi-line lambdas" has been a vexing one for many Python users for a very long time, and it took an exploration of Ruby's @@ -185,7 +197,7 @@ Relation to PEP 3150 -==================== +-------------------- PEP 3150 (Statement Local Namespaces) described its primary motivation as being to elevate ordinary assignment statements to be on par with ``class`` @@ -203,7 +215,7 @@ Keyword Choice -============== +-------------- The proposal definitely requires *some* kind of prefix to avoid parsing ambiguity and backwards compatibility problems with existing constructs. @@ -227,13 +239,14 @@ Better Debugging Support for Functions and Classes with Short Names -=================================================================== +------------------------------------------------------------------- One of the objections to widespread use of lambda expressions is that they have a negative effect on traceback intelligibility and other aspects of -introspection. Similarly objections are raised regarding constructs that +introspection. Similar objections are raised regarding constructs that promote short, cryptic function names (including this one, which requires -that the name of the trailing definition be supplied at least twice) +that the name of the trailing definition be supplied at least twice, +encouraging the use of shorthand placeholder names like ``f``). However, the introduction of qualified names in PEP 3155 means that even anonymous classes and functions will now have different representations if @@ -250,18 +263,8 @@ still a major improvement over the historical situation where everything *except* the object ID was identical. -Syntax Change -============= - -Syntactically, only one new grammar rule is needed:: - - in_stmt: '@in' simple_stmt decorated - -Grammar: http://hg.python.org/cpython/file/default/Grammar/Grammar - - Possible Implementation Strategy -================================ +-------------------------------- This proposal has at least one titanic advantage over PEP 3150: implementation should be relatively straightforward. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Sep 3 13:46:44 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 3 Sep 2012 13:46:44 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315814=3A_Add_NEWS?= =?utf-8?q?_entry_regarding_intended_memoryview_hashing_restrictions?= Message-ID: <3X9Tsw6RTdzQJg@mail.python.org> http://hg.python.org/cpython/rev/c9c9d890400c changeset: 78843:c9c9d890400c user: Nick Coghlan date: Mon Sep 03 21:46:33 2012 +1000 summary: Issue #15814: Add NEWS entry regarding intended memoryview hashing restrictions files: Misc/NEWS | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -85,6 +85,14 @@ calling the C function wadd_wch()/mvwadd_wch() if the Python curses is linked to libncursesw. +Documentation +------------- + +- Issue #15814: The memoryview enhancements in 3.3.0 accidentally permitted + the hashing of multi-dimensional memorviews and memoryviews with multi-byte + item formats. The intended restrictions have now been documented - they + will be correctly enforced in 3.3.1 + What's New in Python 3.3.0 Release Candidate 1? =============================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 3 14:09:40 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 3 Sep 2012 14:09:40 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Tweak_the_equivalence_example?= =?utf-8?q?=2C_explain_why_a_nested_suite_is_a_bad_idea?= Message-ID: <3X9VNN4TQYzQJ6@mail.python.org> http://hg.python.org/peps/rev/9f8c31db2b19 changeset: 4505:9f8c31db2b19 user: Nick Coghlan date: Mon Sep 03 22:09:30 2012 +1000 summary: Tweak the equivalence example, explain why a nested suite is a bad idea files: pep-0403.txt | 27 +++++++++++++++++++++++++-- 1 files changed, 25 insertions(+), 2 deletions(-) diff --git a/pep-0403.txt b/pep-0403.txt --- a/pep-0403.txt +++ b/pep-0403.txt @@ -130,12 +130,14 @@ Under this PEP, an ordinary class or function definition:: + @deco2 + @deco1 def name(): ... -would be equivalent to:: +can be explained as being roughly equivalent to:: - @in name = name + @in name = deco2(deco1(name)) def name(): ... @@ -214,6 +216,27 @@ actual name binding in the current scope. +Why not a nested suite? +----------------------- + +The problem with using a full nested suite is best described by reviewing +PEP 3150. It's ridiculously hard to implement properly, and creates way +too many situations where there are two ways to do it (almost any construct +that can be expressed with ordinary imperative code could instead be +expressed using a given statement). + +By contrast, the decorator inspired syntax explicitly limits the new +feature to cases where it should actually improve readability, rather than +harming it. As in the case of the original introduction of decorators, the +idea of this new syntax is that if it *can* be used (i.e. the local name +binding of the function is completely unnecessary) then it *should* be used. + +While a non-decorator based alternative could be considered (e.g. a nested +"suite" that actually allowed only a single class or function definition), +it seems excessive to introduce a completely new concept when it is +possible to use a variant of the existing decorator syntax instead. + + Keyword Choice -------------- -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Mon Sep 3 18:53:27 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 3 Sep 2012 18:53:27 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1NTA5OiBJZiAl?= =?utf-8?q?action_substitution_produces_a_null_string=2C_drop_it=2E?= Message-ID: <3X9cgq4bfDzQGg@mail.python.org> http://hg.python.org/cpython/rev/6768aa70c2d3 changeset: 78844:6768aa70c2d3 branch: 3.2 parent: 78841:0c6a09b982d8 user: R David Murray date: Mon Sep 03 12:30:12 2012 -0400 summary: #15509: If %action substitution produces a null string, drop it. Patch by Anton Barkovsky, comment addition by me. This showed up as a bug in 3.3 because the definition for Chrome produced such an empty string. This fix is tested in 3.3+; backporting the new test suite is more trouble than it is worth. files: Lib/webbrowser.py | 11 +++++++++-- Misc/NEWS | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -206,12 +206,18 @@ """Parent class for all Unix browsers with remote functionality.""" raise_opts = None + background = False + redirect_stdout = True + # In remote_args, %s will be replaced with the requested URL. %action will + # be replaced depending on the value of 'new' passed to open. + # remote_action is used for new=0 (open). If newwin is not None, it is + # used for new=1 (open_new). If newtab is not None, it is used for + # new=3 (open_new_tab). After both substitutions are made, any empty + # strings in the transformed remote_args list will be removed. remote_args = ['%action', '%s'] remote_action = None remote_action_newwin = None remote_action_newtab = None - background = False - redirect_stdout = True def _invoke(self, args, remote, autoraise): raise_opt = [] @@ -267,6 +273,7 @@ args = [arg.replace("%s", url).replace("%action", action) for arg in self.remote_args] + args = [arg for arg in args if arg] success = self._invoke(args, True, autoraise) if not success: # remote invocation failed, try straight way diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -115,6 +115,9 @@ Library ------- +- Issue #15509: webbrowser.UnixBrowser no longer passes empty arguments to + Popen when %action substitutions produce empty strings. + - Issue #12776,#11839: call argparse type function (specified by add_argument) only once. Before, the type function was called twice in the case where the default was specified and the argument was given as well. This was -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 3 18:53:29 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 3 Sep 2012 18:53:29 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2315509=3A_If_=25action_substitution_produces_a_n?= =?utf-8?q?ull_string=2C_drop_it=2E?= Message-ID: <3X9cgs3nn6zQGt@mail.python.org> http://hg.python.org/cpython/rev/323ca2f0e382 changeset: 78845:323ca2f0e382 parent: 78843:c9c9d890400c parent: 78844:6768aa70c2d3 user: R David Murray date: Mon Sep 03 12:37:59 2012 -0400 summary: Merge #15509: If %action substitution produces a null string, drop it. Patch by Anton Barkovsky, comment addition by me. This shows up as a bug in 3.3 because the definition for Chrome produces such an empty string. Tests will follow. files: Lib/webbrowser.py | 11 +++++++++-- Misc/NEWS | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -206,12 +206,18 @@ """Parent class for all Unix browsers with remote functionality.""" raise_opts = None + background = False + redirect_stdout = True + # In remote_args, %s will be replaced with the requested URL. %action will + # be replaced depending on the value of 'new' passed to open. + # remote_action is used for new=0 (open). If newwin is not None, it is + # used for new=1 (open_new). If newtab is not None, it is used for + # new=3 (open_new_tab). After both substitutions are made, any empty + # strings in the transformed remote_args list will be removed. remote_args = ['%action', '%s'] remote_action = None remote_action_newwin = None remote_action_newtab = None - background = False - redirect_stdout = True def _invoke(self, args, remote, autoraise): raise_opt = [] @@ -264,6 +270,7 @@ args = [arg.replace("%s", url).replace("%action", action) for arg in self.remote_args] + args = [arg for arg in args if arg] success = self._invoke(args, True, autoraise) if not success: # remote invocation failed, try straight way diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #15509: webbrowser.UnixBrowser no longer passes empty arguments to + Popen when %action substitutions produce empty strings. + - Issue #12776,#11839: call argparse type function (specified by add_argument) only once. Before, the type function was called twice in the case where the default was specified and the argument was given as well. This was -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 3 18:53:30 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 3 Sep 2012 18:53:30 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2315447=3A_Use_subprocess?= =?utf-8?q?=2EDEVNULL_in_webbrowser=2C_instead_of_opening?= Message-ID: <3X9cgt74VszQJD@mail.python.org> http://hg.python.org/cpython/rev/901c790e4417 changeset: 78846:901c790e4417 user: R David Murray date: Mon Sep 03 12:44:29 2012 -0400 summary: #15447: Use subprocess.DEVNULL in webbrowser, instead of opening This eliminates a ResourceWarning, since before webbrowser was explicitly opening os.devnull and then leaving it open. Tests to follow. Patch by Anton Barkovsky. files: Lib/webbrowser.py | 4 ++-- Misc/NEWS | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py --- a/Lib/webbrowser.py +++ b/Lib/webbrowser.py @@ -230,7 +230,7 @@ cmdline = [self.name] + raise_opt + args if remote or self.background: - inout = io.open(os.devnull, "r+") + inout = subprocess.DEVNULL else: # for TTY browsers, we need stdin/out inout = None @@ -354,7 +354,7 @@ else: action = "openURL" - devnull = io.open(os.devnull, "r+") + devnull = subprocess.DEVNULL # if possible, put browser in separate process group, so # keyboard interrupts don't affect browser as well as Python setsid = getattr(os, 'setsid', None) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,9 @@ Library ------- +- Issue #15447: Use subprocess.DEVNULL in webbrowser, instead of opening + os.devnull explicitly and leaving it open. + - Issue #15509: webbrowser.UnixBrowser no longer passes empty arguments to Popen when %action substitutions produce empty strings. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 3 18:53:32 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 3 Sep 2012 18:53:32 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbjogIzE1NTU3LCMxNTQ0NywjMTU1?= =?utf-8?q?09=3A_webbrowser_test_suite_added=2E?= Message-ID: <3X9cgw4F6JzQGn@mail.python.org> http://hg.python.org/cpython/rev/5da3b2df38b3 changeset: 78847:5da3b2df38b3 user: R David Murray date: Mon Sep 03 12:52:08 2012 -0400 summary: #15557,#15447,#15509: webbrowser test suite added. Initial patch by Anton Barkovsky, refined a bit by me to further subdivide the test methods. Provides tests for the previous two bug fix commits. files: Lib/test/test_webbrowser.py | 192 ++++++++++++++++++++++++ Misc/NEWS | 3 + 2 files changed, 195 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py new file mode 100644 --- /dev/null +++ b/Lib/test/test_webbrowser.py @@ -0,0 +1,192 @@ +import webbrowser +import unittest +import subprocess +from unittest import mock +from test import support + + +URL = 'http://www.example.com' +CMD_NAME = 'test' + + +class PopenMock(mock.MagicMock): + + def poll(self): + return 0 + + def wait(self, seconds=None): + return 0 + + +class CommandTestMixin: + + def _test(self, meth, *, args=[URL], kw={}, options, arguments): + """Given a web browser instance method name along with arguments and + keywords for same (which defaults to the single argument URL), creates + a browser instance from the class pointed to by self.browser, calls the + indicated instance method with the indicated arguments, and compares + the resulting options and arguments passed to Popen by the browser + instance against the 'options' and 'args' lists. Options are compared + in a position independent fashion, and the arguments are compared in + sequence order to whatever is left over after removing the options. + + """ + popen = PopenMock() + support.patch(self, subprocess, 'Popen', popen) + browser = self.browser_class(name=CMD_NAME) + getattr(browser, meth)(*args, **kw) + popen_args = subprocess.Popen.call_args[0][0] + self.assertEqual(popen_args[0], CMD_NAME) + popen_args.pop(0) + for option in options: + self.assertIn(option, popen_args) + popen_args.pop(popen_args.index(option)) + self.assertEqual(popen_args, arguments) + + +class GenericBrowserCommandTest(CommandTestMixin, unittest.TestCase): + + browser_class = webbrowser.GenericBrowser + + def test_open(self): + self._test('open', + options=[], + arguments=[URL]) + + +class BackgroundBrowserCommandTest(CommandTestMixin, unittest.TestCase): + + browser_class = webbrowser.BackgroundBrowser + + def test_open(self): + self._test('open', + options=[], + arguments=[URL]) + + +class ChromeCommandTest(CommandTestMixin, unittest.TestCase): + + browser_class = webbrowser.Chrome + + def test_open(self): + self._test('open', + options=[], + arguments=[URL]) + + def test_open_with_autoraise_false(self): + self._test('open', kw=dict(autoraise=False), + options=[], + arguments=[URL]) + + def test_open_new(self): + self._test('open_new', + options=['--new-window'], + arguments=[URL]) + + def test_open_new_tab(self): + self._test('open_new_tab', + options=[], + arguments=[URL]) + + +class MozillaCommandTest(CommandTestMixin, unittest.TestCase): + + browser_class = webbrowser.Mozilla + + def test_open(self): + self._test('open', + options=['-raise', '-remote'], + arguments=['openURL({})'.format(URL)]) + + def test_open_with_autoraise_false(self): + self._test('open', kw=dict(autoraise=False), + options=['-noraise', '-remote'], + arguments=['openURL({})'.format(URL)]) + + def test_open_new(self): + self._test('open_new', + options=['-raise', '-remote'], + arguments=['openURL({},new-window)'.format(URL)]) + + def test_open_new_tab(self): + self._test('open_new_tab', + options=['-raise', '-remote'], + arguments=['openURL({},new-tab)'.format(URL)]) + + +class GaleonCommandTest(CommandTestMixin, unittest.TestCase): + + browser_class = webbrowser.Galeon + + def test_open(self): + self._test('open', + options=['-n'], + arguments=[URL]) + + def test_open_with_autoraise_false(self): + self._test('open', kw=dict(autoraise=False), + options=['-noraise', '-n'], + arguments=[URL]) + + def test_open_new(self): + self._test('open_new', + options=['-w'], + arguments=[URL]) + + def test_open_new_tab(self): + self._test('open_new_tab', + options=['-w'], + arguments=[URL]) + + +class OperaCommandTest(CommandTestMixin, unittest.TestCase): + + browser_class = webbrowser.Opera + + def test_open(self): + self._test('open', + options=['-remote'], + arguments=['openURL({})'.format(URL)]) + + def test_open_with_autoraise_false(self): + self._test('open', kw=dict(autoraise=False), + options=['-remote', '-noraise'], + arguments=['openURL({})'.format(URL)]) + + def test_open_new(self): + self._test('open_new', + options=['-remote'], + arguments=['openURL({},new-window)'.format(URL)]) + + def test_open_new(self): + self._test('open_new_tab', + options=['-remote'], + arguments=['openURL({},new-page)'.format(URL)]) + + +class ELinksCommandTest(CommandTestMixin, unittest.TestCase): + + browser_class = webbrowser.Elinks + + def test_open(self): + self._test('open', options=['-remote'], + arguments=['openURL({})'.format(URL)]) + + def test_open_with_autoraise_false(self): + self._test('open', + options=['-remote'], + arguments=['openURL({})'.format(URL)]) + + def test_open_new(self): + self._test('open_new', + options=['-remote'], + arguments=['openURL({},new-window)'.format(URL)]) + + def test_open_new_tab(self): + self._test('open_new_tab', + options=['-remote'], + arguments=['openURL({},new-tab)'.format(URL)]) + + +if __name__=='__main__': + unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -42,6 +42,9 @@ - Issue #15802: Fix test logic in TestMaildir.test_create_tmp. Patch by Serhiy Storchaka. +- Issue #15557: Added a test suite for the webbrowser module, thanks + to Anton Barkovsky. + Build ----- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 3 22:29:40 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 3 Sep 2012 22:29:40 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1ODU1?= =?utf-8?q?=3A_added_docstrings_for_memoryview_methods_and_data_descriptor?= =?utf-8?q?s=2E?= Message-ID: <3X9jTJ4JNgzQHh@mail.python.org> http://hg.python.org/cpython/rev/c49f89261d65 changeset: 78848:c49f89261d65 branch: 3.2 parent: 78844:6768aa70c2d3 user: Alexander Belopolsky date: Mon Sep 03 16:29:11 2012 -0400 summary: Issue #15855: added docstrings for memoryview methods and data descriptors. files: Objects/memoryobject.c | 54 +++++++++++++++++++++++------ 1 files changed, 43 insertions(+), 11 deletions(-) diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -402,14 +402,33 @@ return PyLong_FromLong(self->view.ndim); } -static PyGetSetDef memory_getsetlist[] ={ - {"format", (getter)memory_format_get, NULL, NULL}, - {"itemsize", (getter)memory_itemsize_get, NULL, NULL}, - {"shape", (getter)memory_shape_get, NULL, NULL}, - {"strides", (getter)memory_strides_get, NULL, NULL}, - {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL}, - {"readonly", (getter)memory_readonly_get, NULL, NULL}, - {"ndim", (getter)memory_ndim_get, NULL, NULL}, +PyDoc_STRVAR(memory_format_doc, + "A string containing the format (in struct module style)\n" + " for each element in the view."); +PyDoc_STRVAR(memory_itemsize_doc, + "The size in bytes of each element of the memoryview."); +PyDoc_STRVAR(memory_shape_doc, + "A tuple of ndim integers giving the shape of the memory\n" + " as an N-dimensional array."); +PyDoc_STRVAR(memory_strides_doc, + "A tuple of ndim integers giving the size in bytes to access\n" + " each element for each dimension of the array."); +PyDoc_STRVAR(memory_suboffsets_doc, + "A tuple of integers used internally for PIL-style arrays."); +PyDoc_STRVAR(memory_readonly_doc, + "A bool indicating whether the memory is read only."); +PyDoc_STRVAR(memory_ndim_doc, + "An integer indicating how many dimensions of a multi-dimensional\n" + " array the memory represents."); + +static PyGetSetDef memory_getsetlist[] = { + {"format", (getter)memory_format_get, NULL, memory_format_doc}, + {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc}, + {"shape", (getter)memory_shape_get, NULL, memory_shape_doc}, + {"strides", (getter)memory_strides_get, NULL, memory_strides_doc}, + {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc}, + {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc}, + {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc}, {NULL, NULL, NULL, NULL}, }; @@ -485,10 +504,23 @@ Py_RETURN_NONE; } +PyDoc_STRVAR(memory_release_doc, +"M.release() -> None\n\ +\n\ +Release the underlying buffer exposed by the memoryview object."); +PyDoc_STRVAR(memory_tobytes_doc, +"M.tobytes() -> bytes\n\ +\n\ +Return the data in the buffer as a byte string."); +PyDoc_STRVAR(memory_tolist_doc, +"M.tolist() -> list\n\ +\n\ +Return the data in the buffer as a list of elements."); + static PyMethodDef memory_methods[] = { - {"release", memory_exit, METH_NOARGS}, - {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL}, - {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL}, + {"release", memory_exit, METH_NOARGS, memory_release_doc}, + {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc}, + {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc}, {"__enter__", memory_enter, METH_NOARGS}, {"__exit__", memory_exit, METH_VARARGS}, {NULL, NULL} /* sentinel */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 3 22:44:10 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 3 Sep 2012 22:44:10 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315855=3A_added_docstrings_for_memoryview_method?= =?utf-8?q?s_and_data_descriptors?= Message-ID: <3X9jp20tg5zNWX@mail.python.org> http://hg.python.org/cpython/rev/16a69ccff5ce changeset: 78849:16a69ccff5ce parent: 78847:5da3b2df38b3 parent: 78848:c49f89261d65 user: Alexander Belopolsky date: Mon Sep 03 16:43:55 2012 -0400 summary: Issue #15855: added docstrings for memoryview methods and data descriptors (merge 3.2). files: Objects/memoryobject.c | 51 ++++++++++++++++++++++++----- 1 files changed, 41 insertions(+), 10 deletions(-) diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2861,27 +2861,58 @@ return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags)); } +PyDoc_STRVAR(memory_format_doc, + "A string containing the format (in struct module style)\n" + " for each element in the view."); +PyDoc_STRVAR(memory_itemsize_doc, + "The size in bytes of each element of the memoryview."); +PyDoc_STRVAR(memory_shape_doc, + "A tuple of ndim integers giving the shape of the memory\n" + " as an N-dimensional array."); +PyDoc_STRVAR(memory_strides_doc, + "A tuple of ndim integers giving the size in bytes to access\n" + " each element for each dimension of the array."); +PyDoc_STRVAR(memory_suboffsets_doc, + "A tuple of integers used internally for PIL-style arrays."); +PyDoc_STRVAR(memory_readonly_doc, + "A bool indicating whether the memory is read only."); +PyDoc_STRVAR(memory_ndim_doc, + "An integer indicating how many dimensions of a multi-dimensional\n" + " array the memory represents."); + static PyGetSetDef memory_getsetlist[] = { {"obj", (getter)memory_obj_get, NULL, NULL}, {"nbytes", (getter)memory_nbytes_get, NULL, NULL}, - {"readonly", (getter)memory_readonly_get, NULL, NULL}, - {"itemsize", (getter)memory_itemsize_get, NULL, NULL}, - {"format", (getter)memory_format_get, NULL, NULL}, - {"ndim", (getter)memory_ndim_get, NULL, NULL}, - {"shape", (getter)memory_shape_get, NULL, NULL}, - {"strides", (getter)memory_strides_get, NULL, NULL}, - {"suboffsets", (getter)memory_suboffsets_get, NULL, NULL}, + {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc}, + {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc}, + {"format", (getter)memory_format_get, NULL, memory_format_doc}, + {"ndim", (getter)memory_ndim_get, NULL, memory_ndim_doc}, + {"shape", (getter)memory_shape_get, NULL, memory_shape_doc}, + {"strides", (getter)memory_strides_get, NULL, memory_strides_doc}, + {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc}, {"c_contiguous", (getter)memory_c_contiguous, NULL, NULL}, {"f_contiguous", (getter)memory_f_contiguous, NULL, NULL}, {"contiguous", (getter)memory_contiguous, NULL, NULL}, {NULL, NULL, NULL, NULL}, }; +PyDoc_STRVAR(memory_release_doc, +"M.release() -> None\n\ +\n\ +Release the underlying buffer exposed by the memoryview object."); +PyDoc_STRVAR(memory_tobytes_doc, +"M.tobytes() -> bytes\n\ +\n\ +Return the data in the buffer as a byte string."); +PyDoc_STRVAR(memory_tolist_doc, +"M.tolist() -> list\n\ +\n\ +Return the data in the buffer as a list of elements."); static PyMethodDef memory_methods[] = { - {"release", (PyCFunction)memory_release, METH_NOARGS, NULL}, - {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, NULL}, - {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, NULL}, + {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc}, + {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc}, + {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc}, {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, NULL}, {"__enter__", memory_enter, METH_NOARGS, NULL}, {"__exit__", memory_exit, METH_VARARGS, NULL}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 3 22:51:11 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 3 Sep 2012 22:51:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315855=3A_added_do?= =?utf-8?q?cstrings_for_memoryview_methods_and_data_descriptors_new?= Message-ID: <3X9jy751B1zNk2@mail.python.org> http://hg.python.org/cpython/rev/ba2c1def3710 changeset: 78850:ba2c1def3710 user: Alexander Belopolsky date: Mon Sep 03 16:51:01 2012 -0400 summary: Issue #15855: added docstrings for memoryview methods and data descriptors new in 3.3. files: Objects/memoryobject.c | 41 ++++++++++++++++++++--------- 1 files changed, 28 insertions(+), 13 deletions(-) diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2861,11 +2861,21 @@ return PyBool_FromLong(MV_ANY_CONTIGUOUS(self->flags)); } +PyDoc_STRVAR(memory_obj_doc, + "The underlying object of the memoryview."); +PyDoc_STRVAR(memory_nbytes_doc, + "The amount of space in bytes that the array would use in\n" + " a contiguous representation."); +PyDoc_STRVAR(memory_readonly_doc, + "A bool indicating whether the memory is read only."); +PyDoc_STRVAR(memory_itemsize_doc, + "The size in bytes of each element of the memoryview."); PyDoc_STRVAR(memory_format_doc, "A string containing the format (in struct module style)\n" " for each element in the view."); -PyDoc_STRVAR(memory_itemsize_doc, - "The size in bytes of each element of the memoryview."); +PyDoc_STRVAR(memory_ndim_doc, + "An integer indicating how many dimensions of a multi-dimensional\n" + " array the memory represents."); PyDoc_STRVAR(memory_shape_doc, "A tuple of ndim integers giving the shape of the memory\n" " as an N-dimensional array."); @@ -2874,15 +2884,16 @@ " each element for each dimension of the array."); PyDoc_STRVAR(memory_suboffsets_doc, "A tuple of integers used internally for PIL-style arrays."); -PyDoc_STRVAR(memory_readonly_doc, - "A bool indicating whether the memory is read only."); -PyDoc_STRVAR(memory_ndim_doc, - "An integer indicating how many dimensions of a multi-dimensional\n" - " array the memory represents."); +PyDoc_STRVAR(memory_c_contiguous_doc, + "A bool indicating whether the memory is C contiguous."); +PyDoc_STRVAR(memory_f_contiguous_doc, + "A bool indicating whether the memory is Fortran contiguous."); +PyDoc_STRVAR(memory_contiguous_doc, + "A bool indicating whether the memory is contiguous."); static PyGetSetDef memory_getsetlist[] = { - {"obj", (getter)memory_obj_get, NULL, NULL}, - {"nbytes", (getter)memory_nbytes_get, NULL, NULL}, + {"obj", (getter)memory_obj_get, NULL, memory_obj_doc}, + {"nbytes", (getter)memory_nbytes_get, NULL, memory_nbytes_doc}, {"readonly", (getter)memory_readonly_get, NULL, memory_readonly_doc}, {"itemsize", (getter)memory_itemsize_get, NULL, memory_itemsize_doc}, {"format", (getter)memory_format_get, NULL, memory_format_doc}, @@ -2890,9 +2901,9 @@ {"shape", (getter)memory_shape_get, NULL, memory_shape_doc}, {"strides", (getter)memory_strides_get, NULL, memory_strides_doc}, {"suboffsets", (getter)memory_suboffsets_get, NULL, memory_suboffsets_doc}, - {"c_contiguous", (getter)memory_c_contiguous, NULL, NULL}, - {"f_contiguous", (getter)memory_f_contiguous, NULL, NULL}, - {"contiguous", (getter)memory_contiguous, NULL, NULL}, + {"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc}, + {"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc}, + {"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc}, {NULL, NULL, NULL, NULL}, }; @@ -2908,12 +2919,16 @@ "M.tolist() -> list\n\ \n\ Return the data in the buffer as a list of elements."); +PyDoc_STRVAR(memory_cast_doc, +"M.cast(format[, shape]) -> memoryview\n\ +\n\ +Cast a memoryview to a new format or shape."); static PyMethodDef memory_methods[] = { {"release", (PyCFunction)memory_release, METH_NOARGS, memory_release_doc}, {"tobytes", (PyCFunction)memory_tobytes, METH_NOARGS, memory_tobytes_doc}, {"tolist", (PyCFunction)memory_tolist, METH_NOARGS, memory_tolist_doc}, - {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, NULL}, + {"cast", (PyCFunction)memory_cast, METH_VARARGS|METH_KEYWORDS, memory_cast_doc}, {"__enter__", memory_enter, METH_NOARGS, NULL}, {"__exit__", memory_exit, METH_VARARGS, NULL}, {NULL, NULL} -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 3 23:29:33 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 3 Sep 2012 23:29:33 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315855=3A_updated_?= =?utf-8?q?related_manual_entries=2E?= Message-ID: <3X9kpP6S19zQFy@mail.python.org> http://hg.python.org/cpython/rev/82ae284cd5f1 changeset: 78851:82ae284cd5f1 user: Alexander Belopolsky date: Mon Sep 03 17:29:22 2012 -0400 summary: Issue #15855: updated related manual entries. files: Doc/library/stdtypes.rst | 8 +++++++- 1 files changed, 7 insertions(+), 1 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2687,13 +2687,19 @@ .. attribute:: shape A tuple of integers the length of :attr:`ndim` giving the shape of the - memory as a N-dimensional array. + memory as an N-dimensional array. + + .. versionchanged:: 3.3 + An empty tuple instead of None when ndim = 0. .. attribute:: strides A tuple of integers the length of :attr:`ndim` giving the size in bytes to access each element for each dimension of the array. + .. versionchanged:: 3.3 + An empty tuple instead of None when ndim = 0. + .. attribute:: suboffsets Used internally for PIL-style arrays. The value is informational only. -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Sep 4 05:57:27 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 04 Sep 2012 05:57:27 +0200 Subject: [Python-checkins] Daily reference leaks (82ae284cd5f1): sum=0 Message-ID: results for 82ae284cd5f1 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogJ__EYf', '-x'] From python-checkins at python.org Tue Sep 4 13:33:51 2012 From: python-checkins at python.org (nick.coghlan) Date: Tue, 4 Sep 2012 13:33:51 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Expand_the_discussion_of_nest?= =?utf-8?q?ed_suite_variants?= Message-ID: <3XB5Xb2ClDzQDV@mail.python.org> http://hg.python.org/peps/rev/5377635cedcd changeset: 4506:5377635cedcd user: Nick Coghlan date: Tue Sep 04 21:33:39 2012 +1000 summary: Expand the discussion of nested suite variants files: pep-0403.txt | 167 +++++++++++++++++++++++++++++++------- 1 files changed, 137 insertions(+), 30 deletions(-) diff --git a/pep-0403.txt b/pep-0403.txt --- a/pep-0403.txt +++ b/pep-0403.txt @@ -216,27 +216,6 @@ actual name binding in the current scope. -Why not a nested suite? ------------------------ - -The problem with using a full nested suite is best described by reviewing -PEP 3150. It's ridiculously hard to implement properly, and creates way -too many situations where there are two ways to do it (almost any construct -that can be expressed with ordinary imperative code could instead be -expressed using a given statement). - -By contrast, the decorator inspired syntax explicitly limits the new -feature to cases where it should actually improve readability, rather than -harming it. As in the case of the original introduction of decorators, the -idea of this new syntax is that if it *can* be used (i.e. the local name -binding of the function is completely unnecessary) then it *should* be used. - -While a non-decorator based alternative could be considered (e.g. a nested -"suite" that actually allowed only a single class or function definition), -it seems excessive to introduce a completely new concept when it is -possible to use a variant of the existing decorator syntax instead. - - Keyword Choice -------------- @@ -300,7 +279,9 @@ The one potentially tricky part is changing the meaning of the references to the statement local function or namespace while within the scope of the ``in`` statement, but that shouldn't be too hard to address by maintaining -some additional state within the compiler. +some additional state within the compiler (it's much easier to handle this +for a single name than it is for an unknown number of names in a full +nested suite). More Examples @@ -383,9 +364,32 @@ Rejected Concepts ================= -A previous incarnation of this PEP (see [1]) proposed a much uglier syntax -that (quite rightly) was not well received. The current proposal is -significantly easier both to read and write. +To avoid retreading previously covered ground, some rejected alternatives +are documented in this section. + + +Omitting the decorator prefix character +--------------------------------------- + +Earlier versions of this proposal omitted the ``@`` prefix. However, without +that prefix, the bare ``in`` keyword didn't associate the clause strongly +enough with the subsequent function or class definition. Reusing the +decorator prefix and explicitly characterising the new construct as a kind +of decorator clause is intended to help users link the two concepts and +see them as two variants of the same idea. + + +Anonymous Forward References +---------------------------- + +A previous incarnation of this PEP (see [1]) proposed a syntax where the +new clause was introduced with ``:`` and the forward reference was written +using ``@``. Feedback on this variant was almost universally +negative, as it was considered both ugly and excessively magical:: + + :x = weakref.ref(target, @) + def report_destruction(obj): + print("{} is being destroyed".format(obj)) A more recent variant always used ``...`` for forward references, along with genuinely anonymous function and class definitions. However, this @@ -403,11 +407,114 @@ a = calculate_a() b = calculate_b() -Another past alternative omitted the ``@`` prefix. However, without that -prefix, the bare ``in`` keyword didn't associate the clause strongly -enough with the subsequent function or class definition. Reusing the -decorator prefix and explicitly characterising the new construct as a kind -of decorator clause should address that problem. + +Using a nested suite +-------------------- + +The problems with using a full nested suite are best described in +PEP 3150. It's comparatively difficult to implement properly, the scoping +semantics are hard to explain and it creates quite a few situations where +there are two ways to do it without clear guidelines for choosing between +them (as almost any construct that can be expressed with ordinary imperative +code could instead be expressed using a given statement). While the PEP did +propose some new PEP 8 guidelines to help address that last problem, the +difficulties in implementation and explanation are not so easily dealt with. + +By contrast, the decorator inspired syntax in this PEP explicitly limits the +new feature to cases where it should actually improve readability, rather +than harming it. As in the case of the original introduction of decorators, +the idea of this new syntax is that if it *can* be used (i.e. the local name +binding of the function is completely unnecessary) then it *should* be used. + +Another possible variant of this idea is to keep the decorator based +*semantics* of this PEP, while adopting the prettier syntax from PEP 3150:: + + x = weakref.ref(target, report_destruction) given: + def report_destruction(obj): + print("{} is being destroyed".format(obj)) + +There are a couple of problems with this approach. The main issue is that +this syntax variant uses something that looks like a suite, but really isn't +one. A secondary concern is that it's not clear how the compiler will know +which name(s) in the leading expression are forward references (although +that could potentially be addressed through a suitable definition of the +suite-that-is-not-a-suite in the languge grammar). + +There's yet another possibility which would require names to be explicitly +lifted out of the private namespace, eliminating much of the implementation +complexity discussed in PEP 3150 (as only identifiers would be exported, +rather than arbitrary subexpressions):: + + x = weakref.ref(target, report_destruction) given report_destruction from: + def report_destruction(obj): + print("{} is being destroyed".format(obj)) + +or even:: + + x = weakref.ref(target, f) given report_destruction as f from: + def report_destruction(obj): + print("{} is being destroyed".format(obj)) + +This approach actually has much to recommend it. It's as powerful as +PEP 3150 while being substantially simpler both to implement and to +explain. The main downside is that it requires even *more* repetition +of names than is needed with the proposed ``@in`` decorator based syntax +or with the status quo where the function is defined and bound to a local +name prior to its sole use. + +Some more examples using this last variant:: + + sorted_list = sorted(original, key=f) given f from: + def f(item): + try: + return item.calc_sort_order() + except NotSortableError: + return float('inf') + + funcs = [adder(i) for i in range(10)] given adder from: + def adder(i): + return lambda x: x + i + + environ = _createenviron() given _createenviron from: + def _createenviron(): + ... # 27 line function + + c = math.sqrt(a*a + b*b) given a, b from: + a = calculate_a() + b = calculate_b() + + dispatch[MyClass] = f given f from: + def f(): + ... + + f() given f from: + def f(): + ... + +One interesting outcome of such an approach is that it allows the semantics +of function decoration to be represented almost exactly as a specific +case of the new syntax:: + + # @deco2 + # @deco1 + # def name(): + # ... + + name = f given f from: + # Decorator expressions are evaluated first, in code order + _d2 = deco2 + _d1 = deco1 + + # The base function object is defined + def name(): + ... + + # Decorators are applied innermost first + f = _d2(_d1(name)) + +Hmm, perhaps PEP 3150 isn't *quite* as dead as I thought, although the +triple repetition of names is still a rather large downside. + References ========== -- Repository URL: http://hg.python.org/peps From solipsis at pitrou.net Wed Sep 5 06:03:19 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 05 Sep 2012 06:03:19 +0200 Subject: [Python-checkins] Daily reference leaks (82ae284cd5f1): sum=0 Message-ID: results for 82ae284cd5f1 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogS94519', '-x'] From python-checkins at python.org Wed Sep 5 13:15:11 2012 From: python-checkins at python.org (nick.coghlan) Date: Wed, 5 Sep 2012 13:15:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Updating_PEP_3150=27s_stateme?= =?utf-8?q?nt_local_namespaces_to_be_substantially_simpler_and?= Message-ID: <3XBj4b2fwDzQ4M@mail.python.org> http://hg.python.org/peps/rev/2f04a362718c changeset: 4507:2f04a362718c user: Nick Coghlan date: Wed Sep 05 21:15:00 2012 +1000 summary: Updating PEP 3150's statement local namespaces to be substantially simpler and easier to understand, and make PEP 403 and PEP 3150 direct competitors again files: pep-0403.txt | 149 +++----- pep-3150.txt | 650 +++++++++++++++++--------------------- 2 files changed, 361 insertions(+), 438 deletions(-) diff --git a/pep-0403.txt b/pep-0403.txt --- a/pep-0403.txt +++ b/pep-0403.txt @@ -1,5 +1,5 @@ PEP: 403 -Title: General purpose decorator clause +Title: General purpose decorator clause (aka "@in" clause) Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan @@ -209,11 +209,16 @@ the simple name binding of a standard function definition to be replaced with something else (like assigning the result of the function to a value). -This PEP also achieves most of the other effects described in PEP 3150 -without introducing a new brainbending kind of scope. All of the complex -scoping rules in PEP 3150 are replaced in this PEP with allowing a forward -reference to the associated function or class definition without creating an -actual name binding in the current scope. +Despite having the same author, the two PEPs are in direct competition with +each other. This PEP represents a minimalist approach that attempts to +achieve useful functionality with a minimum of change from the status quo. +PEP 3150 instead aims for a more flexible standalone statement design, which +requires a larger degree of change to the language. + +Note that where this PEP is better suited to explaining the behaviour of +generator expressions correctly, PEP 3150 is better able to explain the +behaviour of decorator clauses in general. Both PEPs support adequate +explanations for the semantics of container comprehensions. Keyword Choice @@ -284,6 +289,47 @@ nested suite). +Explaining Container Comprehensions and Generator Expressions +------------------------------------------------------------- + +One interesting feature of the proposed construct is that it can be used as +a primitive to explain the scoping and execution order semantics of +both generator expressions and container comprehensions:: + + seq2 = [x for x in y if q(x) for y in seq if p(y)] + + # would be equivalent to + + @in seq2 = f(seq): + def f(seq) + result = [] + for y in seq: + if p(y): + for x in y: + if q(x): + result.append(x) + return result + +The important point in this expansion is that it explains why comprehensions +appear to misbehave at class scope: only the outermost iterator is evaluated +at class scope, while all predicates, nested iterators and value expressions +are evaluated inside a nested scope. + +An equivalent expansion is possible for generator expressions:: + + gen = (x for x in y if q(x) for y in seq if p(y)) + + # would be equivalent to + + @in gen = g(seq): + def g(seq) + for y in seq: + if p(y): + for x in y: + if q(x): + yield x + + More Examples ============= @@ -413,18 +459,19 @@ The problems with using a full nested suite are best described in PEP 3150. It's comparatively difficult to implement properly, the scoping -semantics are hard to explain and it creates quite a few situations where +semantics are harder to explain and it creates quite a few situations where there are two ways to do it without clear guidelines for choosing between them (as almost any construct that can be expressed with ordinary imperative -code could instead be expressed using a given statement). While the PEP did +code could instead be expressed using a given statement). While the PEP does propose some new PEP 8 guidelines to help address that last problem, the -difficulties in implementation and explanation are not so easily dealt with. +difficulties in implementation are not so easily dealt with. By contrast, the decorator inspired syntax in this PEP explicitly limits the new feature to cases where it should actually improve readability, rather than harming it. As in the case of the original introduction of decorators, the idea of this new syntax is that if it *can* be used (i.e. the local name -binding of the function is completely unnecessary) then it *should* be used. +binding of the function is completely unnecessary) then it probably *should* +be used. Another possible variant of this idea is to keep the decorator based *semantics* of this PEP, while adopting the prettier syntax from PEP 3150:: @@ -438,82 +485,14 @@ one. A secondary concern is that it's not clear how the compiler will know which name(s) in the leading expression are forward references (although that could potentially be addressed through a suitable definition of the -suite-that-is-not-a-suite in the languge grammar). +suite-that-is-not-a-suite in the language grammar). -There's yet another possibility which would require names to be explicitly -lifted out of the private namespace, eliminating much of the implementation -complexity discussed in PEP 3150 (as only identifiers would be exported, -rather than arbitrary subexpressions):: - - x = weakref.ref(target, report_destruction) given report_destruction from: - def report_destruction(obj): - print("{} is being destroyed".format(obj)) - -or even:: - - x = weakref.ref(target, f) given report_destruction as f from: - def report_destruction(obj): - print("{} is being destroyed".format(obj)) - -This approach actually has much to recommend it. It's as powerful as -PEP 3150 while being substantially simpler both to implement and to -explain. The main downside is that it requires even *more* repetition -of names than is needed with the proposed ``@in`` decorator based syntax -or with the status quo where the function is defined and bound to a local -name prior to its sole use. - -Some more examples using this last variant:: - - sorted_list = sorted(original, key=f) given f from: - def f(item): - try: - return item.calc_sort_order() - except NotSortableError: - return float('inf') - - funcs = [adder(i) for i in range(10)] given adder from: - def adder(i): - return lambda x: x + i - - environ = _createenviron() given _createenviron from: - def _createenviron(): - ... # 27 line function - - c = math.sqrt(a*a + b*b) given a, b from: - a = calculate_a() - b = calculate_b() - - dispatch[MyClass] = f given f from: - def f(): - ... - - f() given f from: - def f(): - ... - -One interesting outcome of such an approach is that it allows the semantics -of function decoration to be represented almost exactly as a specific -case of the new syntax:: - - # @deco2 - # @deco1 - # def name(): - # ... - - name = f given f from: - # Decorator expressions are evaluated first, in code order - _d2 = deco2 - _d1 = deco1 - - # The base function object is defined - def name(): - ... - - # Decorators are applied innermost first - f = _d2(_d1(name)) - -Hmm, perhaps PEP 3150 isn't *quite* as dead as I thought, although the -triple repetition of names is still a rather large downside. +However, a nested suite has not yet been ruled out completely. The latest +version of PEP 3150 uses explicit forward reference and name binding +schemes that greatly simplify the semantics of the statement, and it +does offer the advantage of allowing the definition of arbitrary +subexpressions rather than being restricted to a single function or +class definition. References diff --git a/pep-3150.txt b/pep-3150.txt --- a/pep-3150.txt +++ b/pep-3150.txt @@ -3,7 +3,7 @@ Version: $Revision$ Last-Modified: $Date$ Author: Nick Coghlan -Status: Withdrawn +Status: Deferred Type: Standards Track Content-Type: text/x-rst Created: 2010-07-09 @@ -19,7 +19,9 @@ Python statements that do not currently have an associated code suite. This clause will create a statement local namespace for additional names that are accessible in the associated statement, but do not become part of the -containing namespace. +containing namespace. To permit a sane implementation strategy, forward +references to names from the ``given`` clause will need to be marked +explicitly. The primary motivation is to enable a more declarative style of programming, where the operation to be performed is presented to the reader first, and the @@ -47,23 +49,6 @@ but has not yet itself been subject to the test of implementation. -PEP Withdrawal -============== - -I've had a complicated history with this PEP. For a long time I left it in -the Deferred state because I wasn't convinced the additional complexity was -worth the payoff. Then, briefly, I became more enamoured of the idea and -only left it at Deferred because I didn't really have time to pursue it. - -I'm now withdrawing it, as, the longer I reflect on the topic, the more I -feel this approach is simply far too intrusive and complicated to ever be -a good idea for Python as a language. - -I've also finally found a couple of syntax proposals for PEP 403 that -read quite nicely and address the same set of use cases as this PEP -while remaining significantly simpler. - - Proposal ======== @@ -87,16 +72,171 @@ name in the header line, with the actual definitions following in the indented clause. As a simple example:: - sorted_data = sorted(data, key=sort_key) given: + sorted_data = sorted(data, key=.sort_key) given: def sort_key(item): return item.attr1, item.attr2 +The leading ``.`` on ``.sort_key`` indicates to the compiler that this +is a forward reference to a name defined in the ``given`` clause. + The ``pass`` statement is included to provide a consistent way to skip inclusion of a meaningful expression in the header line. While this is not an intended use case, it isn't one that can be prevented as multiple alternatives (such as ``...`` and ``()``) remain available even if ``pass`` itself is disallowed. +The body of the given clause will execute in a new scope, using normal +function closure semantics. To support early binding of loop variables +and global references, as well as to allow access to other names defined at +class scope, the ``given`` clause will also allow explicit +binding operations in the header line:: + + # Explicit early binding via given clause + seq = [] + for i in range(10): + seq.append(.f) given i=i: + def f(): + return i + assert [f() for f in seq] == list(range(10)) + + +Semantics +--------- + +The following statement:: + + op(.f, .g) given bound_a=a, bound_b=b: + def f(): + return bound_a + bound_b + def g(): + return bound_a - bound_b + +Would be roughly equivalent to the following code (``__var`` denotes a +hidden compiler variable or simply an entry on the interpreter stack):: + + __arg1 = a + __arg2 = b + def __scope(bound_a, bound_b): + def f(): + return bound_a + bound_b + def g(): + return bound_a - bound_b + return f, g + __ref1, __ref2 = __scope(__arg1) + op(__ref1, __ref2) + +A ``given`` clause is essentially a nested function which is created and +then immediately executed. Unless explicitly passed in, names are looked +up using normal scoping rules, and thus names defined at class scope will +not be visible. Names declared as forward references are returned and +used in the header statement, without being bound locally in the +surrounding namespace. + + +Syntax Change +------------- + +Current:: + + expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | + ('=' (yield_expr|testlist_star_expr))*) + del_stmt: 'del' exprlist + pass_stmt: 'pass' + return_stmt: 'return' [testlist] + yield_stmt: yield_expr + raise_stmt: 'raise' [test ['from' test]] + assert_stmt: 'assert' test [',' test] + + +New:: + + expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | + ('=' (yield_expr|testlist_star_expr))*) [given_clause] + del_stmt: 'del' exprlist [given_clause] + pass_stmt: 'pass' [given_clause] + return_stmt: 'return' [testlist] [given_clause] + yield_stmt: yield_expr [given_clause] + raise_stmt: 'raise' [test ['from' test]] [given_clause] + assert_stmt: 'assert' test [',' test] [given_clause] + given_clause: "given" (NAME '=' test)* ":" suite + +(Note that ``expr_stmt`` in the grammar is a slight misnomer, as it covers +assignment and augmented assignment in addition to simple expression +statements) + +The new clause is added as an optional element of the existing statements +rather than as a new kind of compound statement in order to avoid creating +an ambiguity in the grammar. It is applied only to the specific elements +listed so that nonsense like the following is disallowed:: + + break given: + a = b = 1 + + import sys given: + a = b = 1 + +However, the precise Grammar change described above is inadequate, as it +creates problems for the definition of simple_stmt (which allows chaining of +multiple single line statements with ";" rather than "\\n"). + +So the above syntax change should instead be taken as a statement of intent. +Any actual proposal would need to resolve the simple_stmt parsing problem +before it could be seriously considered. This would likely require a +non-trivial restructuring of the grammar, breaking up small_stmt and +flow_stmt to separate the statements that potentially contain arbitrary +subexpressions and then allowing a single one of those statements with +a ``given`` clause at the simple_stmt level. Something along the lines of:: + + stmt: simple_stmt | given_stmt | compound_stmt + simple_stmt: small_stmt (';' (small_stmt | subexpr_stmt))* [';'] NEWLINE + small_stmt: (pass_stmt | flow_stmt | import_stmt | + global_stmt | nonlocal_stmt) + flow_stmt: break_stmt | continue_stmt + given_stmt: subexpr_stmt (given_clause | + (';' (small_stmt | subexpr_stmt))* [';']) NEWLINE + subexpr_stmt: expr_stmt | del_stmt | flow_subexpr_stmt | assert_stmt + flow_subexpr_stmt: return_stmt | raise_stmt | yield_stmt + given_clause: "given" (NAME '=' test)* ":" suite + +For reference, here are the current definitions at that level:: + + stmt: simple_stmt | compound_stmt + simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE + small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | + import_stmt | global_stmt | nonlocal_stmt | assert_stmt) + flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt + +In addition to the above changes, the definition of ``atom`` would be changed +to also allow ``"." NAME``. The restriction of this usage to statements with +an associated ``given`` clause would be handled by a later stage of the +compilation process (likely AST construction, which already enforces +other restrictions where the grammar is overly permissive in order to +simplify the initial parsing step). + + +New PEP 8 Guidelines +-------------------- + +As discussed on python-ideas ([7]_, [9]_) new PEP 8 guidelines would also +need to be developed to provide appropriate direction on when to use the +``given`` clause over ordinary variable assignments. + +Based on the similar guidelines already present for ``try`` statements, this +PEP proposes the following additions for ``given`` statements to the +"Programming Conventions" section of PEP 8: + + - for code that could reasonably be factored out into a separate function, + but is not currently reused anywhere, consider using a ``given`` clause. + This clearly indicates which variables are being used only to define + subcomponents of another statement rather than to hold algorithm or + application state. This is an especially useful technique when + passing multi-line functions to operations which take callable + arguments. + + - keep ``given`` clauses concise. If they become unwieldy, either break + them up into multiple steps or else move the details into a separate + function. + Rationale ========= @@ -152,11 +292,14 @@ One potentially useful way to think of the proposed clause is as a middle ground between conventional in-line code and separation of an operation out into a dedicated function, just as an inline while loop may -eventually be factored out into a dedicator generator. +eventually be factored out into a dedicated generator. +Design Discussion +================= + Keyword Choice -============== +-------------- This proposal initially used ``where`` based on the name of a similar construct in Haskell. However, it has been pointed out that there @@ -177,12 +320,86 @@ That way lies C++ and Perl :) +Relation to PEP 403 +------------------- + +PEP 403 (General Purpose Decorator Clause) attempts to achieve the main +goals of this PEP using a less radical language change inspired by the +existing decorator syntax. + +Despite having the same author, the two PEPs are in direct competition with +each other. PEP 403 represents a minimalist approach that attempts to achieve +useful functionality with a minimum of change from the status quo. This PEP +instead aims for a more flexible standalone statement design, which requires +a larger degree of change to the language. + +Note that where PEP 403 is better suited to explaining the behaviour of +generator expressions correctly, this PEP is better able to explain the +behaviour of decorator clauses in general. Both PEPs support adequate +explanations for the semantics of container comprehensions. + + +Explaining Container Comprehensions and Generator Expressions +------------------------------------------------------------- + +One interesting feature of the proposed construct is that it can be used as +a primitive to explain the scoping and execution order semantics of +container comprehensions:: + + seq2 = [x for x in y if q(x) for y in seq if p(y)] + + # would be equivalent to + + seq2 = .result given seq=seq: + result = [] + for y in seq: + if p(y): + for x in y: + if q(x): + result.append(x) + +The important point in this expansion is that it explains why comprehensions +appear to misbehave at class scope: only the outermost iterator is evaluated +at class scope, while all predicates, nested iterators and value expressions +are evaluated inside a nested scope. + +Not that, unlike PEP 403, the current version of this PEP *cannot* +provide a precisely equivalent expansion for a generator expression. The +closest it can get is to define an additional level of scoping:: + + seq2 = .g(seq) given: + def g(seq): + for y in seq: + if p(y): + for x in y: + if q(x): + yield x + +Explaining Decorator Clause Evaluation and Application +------------------------------------------------------ + +The standard explanation of decorator clause evaluation and application +has to deal with the idea of hidden compiler variables in order to show +steps in their order of execution. The given statement allows a decorated +function definition like:: + + @classmethod + def classname(cls): + return cls.__name__ + +To instead be explained as roughly equivalent to:: + + classname = .d1(classname) given: + d1 = classmethod + def classname(cls): + return cls.__name__ + Anticipated Objections -====================== +---------------------- Two Ways To Do It ------------------ +~~~~~~~~~~~~~~~~~ A lot of code may now be written with values defined either before the expression where they are used or afterwards in a ``given`` clause, creating @@ -203,11 +420,11 @@ Opinions differ, and that's OK. However, explicit PEP 8 guidance will be needed for CPython and the standard -library, and that is discussed below. +library, and that is discussed in the proposal above. Out of Order Execution ----------------------- +~~~~~~~~~~~~~~~~~~~~~~ The ``given`` clause makes execution jump around a little strangely, as the body of the ``given`` clause is executed before the simple statement in the @@ -231,7 +448,7 @@ sorted_list = sorted(original, key=(lambda v: v.attr1, v.attr2)) That gets the job done, but it hardly reaches the standard of ``executable -pseudocode`` that Python aspires to, does it? +pseudocode`` that fits Python's reputation. If they don't like ``lambda`` specifically, the ``operator`` module offers an alternative that still allows the key function to be defined inline:: @@ -239,7 +456,8 @@ sorted_list = sorted(original, key=operator.attrgetter(v. 'attr1', 'attr2')) -Again, it gets the job done, but executable pseudocode it ain't. +Again, it gets the job done, but even the most generous of readers would + not consider that to be "executable pseudocode". If they think both of the above options are ugly and confusing, or they need logic in their key function that can't be expressed as an expression (such @@ -256,47 +474,20 @@ but it really does represent a break between what the user is thinking and what the language allows them to express. -I believe the proposal in this PEP will finally let Python get close to the +I believe the proposal in this PEP would finally let Python get close to the "executable pseudocode" bar for the kind of thought expressed above:: - sorted_list = sorted(original, key=sort_key) given: + sorted_list = sorted(original, key=.sort_key) given: def sort_key(item): return item.attr1, item.attr2 Everything is in the same order as it was in the user's original thought, the only addition they have to make is to give the sorting criteria a name so that the usage can be linked up to the subsequent definition. - -One other useful note on this front, is that this PEP allows existing out of -order execution constructs to be described as special cases of the more -general out of order execution syntax (just as comprehensions are now special -cases of the more general generator expression syntax, even though list -comprehensions existed first):: - - @classmethod - def classname(cls): - return cls.__name__ - -Would be roughly equivalent to:: - - classname = f1(classname) given: - f1 = classmethod - def classname(cls): - return cls.__name__ - -A list comprehension like ``squares = [x*x for x in range(10)]`` -would be equivalent to:: - - # Note: this example uses an explicit early binding variant that - # isn't yet reflected in the rest of the PEP. It will get there, though. - squares = seq given outermost=range(10): - seq = [] - for x in outermost: - seq.append(x*x) Harmful to Introspection ------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~ Poking around in module and class internals is an invaluable tool for white-box testing and interactive debugging. The ``given`` clause will be @@ -314,7 +505,7 @@ Lack of Real World Impact Assessment ------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The examples in the current PEP are almost all relatively small "toy" examples. The proposal in this PEP needs to be subjected to the test of @@ -322,261 +513,32 @@ Twisted application) in a search for examples where the readability of real world code is genuinely enhanced. -This is more of a deficiency in the PEP rather than the idea, though. +This is more of a deficiency in the PEP rather than the idea, though. If +it wasn't a real world problem, we wouldn't get so many complaints about +the lack of multi-line lambda support and Ruby's block construct +probaly wouldn't be quite so popular. -New PEP 8 Guidelines -==================== +Open Questions +============== -As discussed on python-ideas ([7]_, [9]_) new PEP 8 guidelines would also -need to be developed to provide appropriate direction on when to use the -``given`` clause over ordinary variable assignments. - -Based on the similar guidelines already present for ``try`` statements, this -PEP proposes the following additions for ``given`` statements to the -"Programming Conventions" section of PEP 8: - - - for code that could reasonably be factored out into a separate function, - but is not currently reused anywhere, consider using a ``given`` clause. - This clearly indicates which variables are being used only to define - subcomponents of another statement rather than to hold algorithm or - application state. - - - keep ``given`` clauses concise. If they become unwieldy, either break - them up into multiple steps or else move the details into a separate - function. - - -Syntax Change -============= - -Current:: - - expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | - ('=' (yield_expr|testlist_star_expr))*) - del_stmt: 'del' exprlist - pass_stmt: 'pass' - return_stmt: 'return' [testlist] - yield_stmt: yield_expr - raise_stmt: 'raise' [test ['from' test]] - assert_stmt: 'assert' test [',' test] - - -New:: - - expr_stmt: testlist_star_expr (augassign (yield_expr|testlist) | - ('=' (yield_expr|testlist_star_expr))*) [given_clause] - del_stmt: 'del' exprlist [given_clause] - pass_stmt: 'pass' [given_clause] - return_stmt: 'return' [testlist] [given_clause] - yield_stmt: yield_expr [given_clause] - raise_stmt: 'raise' [test ['from' test]] [given_clause] - assert_stmt: 'assert' test [',' test] [given_clause] - given_clause: "given" ":" suite - -(Note that ``expr_stmt`` in the grammar is a slight misnomer, as it covers -assignment and augmented assignment in addition to simple expression -statements) - -The new clause is added as an optional element of the existing statements -rather than as a new kind of compound statement in order to avoid creating -an ambiguity in the grammar. It is applied only to the specific elements -listed so that nonsense like the following is disallowed:: - - break given: - a = b = 1 - - import sys given: - a = b = 1 - -However, the precise Grammar change described above is inadequate, as it -creates problems for the definition of simple_stmt (which allows chaining of -multiple single line statements with ";" rather than "\\n"). - -So the above syntax change should instead be taken as a statement of intent. -Any actual proposal would need to resolve the simple_stmt parsing problem -before it could be seriously considered. This would likely require a -non-trivial restructuring of the grammar, breaking up small_stmt and -flow_stmt to separate the statements that potentially contain arbitrary -subexpressions and then allowing a single one of those statements with -a ``given`` clause at the simple_stmt level. Something along the lines of:: - - stmt: simple_stmt | given_stmt | compound_stmt - simple_stmt: small_stmt (';' (small_stmt | subexpr_stmt))* [';'] NEWLINE - small_stmt: (pass_stmt | flow_stmt | import_stmt | - global_stmt | nonlocal_stmt) - flow_stmt: break_stmt | continue_stmt - given_stmt: subexpr_stmt (given_clause | - (';' (small_stmt | subexpr_stmt))* [';']) NEWLINE - subexpr_stmt: expr_stmt | del_stmt | flow_subexpr_stmt | assert_stmt - flow_subexpr_stmt: return_stmt | raise_stmt | yield_stmt - given_clause: "given" ":" suite - -For reference, here are the current definitions at that level:: - - stmt: simple_stmt | compound_stmt - simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE - small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt | - import_stmt | global_stmt | nonlocal_stmt | assert_stmt) - flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt - - -Possible Implementation Strategy -================================ - -Torture Test ------------- - -An implementation of this PEP should support execution of the following -code at module, class and function scope:: - - b = {} - a = b[f(a)] = x given: - x = 42 - def f(x): - return x - assert "x" not in locals() - assert "f" not in locals() - assert a == 42 - assert d[42] == 42 given: - d = b - assert "d" not in locals() - y = y given: - x = 42 - def f(): pass - y = locals("x"), f.__name__ - assert "x" not in locals() - assert "f" not in locals() - assert y == (42, "f") - -Most naive implementations will choke on the first complex assignment, -while less naive but still broken implementations will fail when -the torture test is executed at class scope. Renaming based strategies -struggle to support ``locals()`` correctly and also have problems with -class and function ``__name__`` attributes. - -And yes, that's a perfectly well-defined assignment statement. Insane, -you might rightly say, but legal:: - - >>> def f(x): return x - ... - >>> x = 42 - >>> b = {} - >>> a = b[f(a)] = x - >>> a - 42 - >>> b - {42: 42} - -Details of Proposed Semantics +Syntax for Forward References ----------------------------- -AKA How Class Scopes Screw You When Attempting To Implement This +The leading ``.`` arguably fails the "syntax shall not look like grit on +Uncle Tim's monitor" test. However, it does have the advantages of being +easy to type and already having an association with namespaces. -The natural idea when setting out to implement this concept is to -use an ordinary nested function scope. This doesn't work for the -two reasons mentioned in the Torture Test section above: -* Non-local variables are not your friend because they ignore class scopes - and (when writing back to the outer scope) aren't really on speaking - terms with module scopes either. +Handling of ``nonlocal`` and ``global`` +--------------------------------------- -* Return-based semantics struggle with complex assignment statements - like the one in the torture test +``nonlocal`` and ``global`` are explicitly disallowed in the ``given`` clause +suite and will be syntax errors if they occur. They will work normally if +they appear within a ``def`` statement within that suite. -The second thought is generally some kind of hidden renaming strategy. This -also creates problems, as Python exposes variables names via the ``locals()`` -dictionary and class and function ``__name__`` attributes. - -The most promising approach is one based on symtable analysis and -copy-in-copy-out referencing semantics to move any required name -bindings between the inner and outer scopes. The torture test above -would then translate to something like the following:: - - b = {} - def _anon1(b): # 'b' reference copied in - x = 42 - def f(x): - return x - a = b[f(a)] = x - return a # 'a' reference copied out - a = _anon1(b) - assert "x" not in locals() - assert "f" not in locals() - assert a == 42 - def _anon2(b) # 'b' reference copied in - d = b - assert d[42] == 42 - # Nothing to copy out (not an assignment) - _anon2() - assert "d" not in locals() - def _anon3() # Nothing to copy in (no references to other variables) - x = 42 - def f(): pass - y = locals("x"), f.__name__ - y = y # Assuming no optimisation of special cases - return y # 'y' reference copied out - y = _anon3() - assert "x" not in locals() - assert "f" not in locals() - assert y == (42, "f") - -However, as noted in the abstract, an actual implementation of -this idea has never been tried. - - -Detailed Semantics #1: Early Binding of Variable References ------------------------------------------------------------ - -The copy-in-copy-out semantics mean that all variable references from a -``given`` clause will exhibit early binding behaviour, in contrast to the -late binding typically seen with references to closure variables and globals -in ordinary functions. This behaviour will allow the ``given`` clause to -be used as a substitute for the default argument hack when early binding -behaviour is desired:: - - # Current Python (late binding) - seq = [] - for i in range(10): - def f(): - return i - seq.append(f) - assert [f() for f in seq] == [9]*10 - - # Current Python (early binding via default argument hack) - seq = [] - for i in range(10): - def f(_i=i): - return i - seq.append(f) - assert [f() for f in seq] == list(range(10)) - - # Early binding via given clause - seq = [] - for i in range(10): - seq.append(f) given: - def f(): - return i - assert [f() for f in seq] == list(range(10)) - -Note that the current intention is for the copy-in/copy-out semantics to -apply only to names defined in the local scope containing the ``given`` -clause. Name in outer scopes will be referenced as normal. - -This intention is subject to revision based on feedback and practicalities -of implementation. - - -Detailed Semantics #2: Handling of ``nonlocal`` and ``global`` --------------------------------------------------------------- - -``nonlocal`` and ``global`` will largely operate as if the anonymous -functions were defined as in the expansion above. However, they will also -override the default early-binding semantics for names from the containing -scope. - -This intention is subject to revision based on feedback and practicalities -of implementation. +Alternatively, they could be defined as operating as if the anonymous +functions were defined as in the expansion above. Detailed Semantics #3: Handling of ``break`` and ``continue`` @@ -588,53 +550,14 @@ a ``for`` or ``while`` loop as part of that suite. -Detailed Semantics #4: Handling of ``return`` and ``yield`` -------------------------------------------------------------- +Handling of ``return`` and ``yield`` +------------------------------------ ``return`` and ``yield`` are explicitly disallowed in the ``given`` clause suite and will be syntax errors if they occur. They will work normally if they appear within a ``def`` statement within that suite. -Alternative Semantics for Name Binding --------------------------------------- - -The "early binding" semantics proposed for the ``given`` clause are driven -by the desire to have ``given`` clauses work "normally" in class scopes (that -is, allowing them to see the local variables in the class, even though classes -do not participate in normal lexical scoping). - -There is an alternative, which is to simply declare that the ``given`` clause -creates an ordinary nested scope, just like comprehensions and generator -expressions. Thus, the given clause would share the same quirks as those -constructs: they exhibit surprising behaviour at class scope, since they -can't see the local variables in the class definition. While this behaviour -is considered desirable for method definitions (where class variables are -accessed via the class or instance argument passed to the method), it can be -surprising and inconvenient for implicit scopes that are designed to hide -their own name bindings from the containing scope rather than vice-versa. - -A third alternative, more analogous to the comprehension case (where the -outermost iterator expression is evaluated in the current scope and hence can -see class locals normally), would be to allow *explicit* early binding in the -``given`` clause, by passing an optional tuple of assignments after the -``given`` keyword:: - - # Explicit early binding via given clause - seq = [] - for i in range(10): - seq.append(f) given i=i: - def f(): - return i - assert [f() for f in seq] == list(range(10)) - -(Note: I actually like the explicit early binding idea significantly more -than I do the implicit early binding - expect a future version of the PEP -to be updated accordingly. I've already used it above when describing how -an existing construct like a list comprehension could be expressed as a -special case of the new syntax) - - Examples ======== @@ -654,10 +577,9 @@ @singleton(*params) class public_name(): ... # However many lines - public_name = public_name(*params) # Becomes: - public_name = MeaningfulClassName(*params) given: + public_name = .MeaningfulClassName(*params) given: class MeaningfulClassName(): ... # Should trawl the stdlib for an example of doing this @@ -671,7 +593,7 @@ del _createenviron # Becomes: - environ = _createenviron() given: + environ = ._createenviron() given: def _createenviron(): ... # 27 line function @@ -684,7 +606,7 @@ return decorating_function # Becomes: - return decorating_function given: + return .decorating_function given: # Cell variables rather than locals, but should give similar speedup tuple, sorted, len, KeyError = tuple, sorted, len, KeyError def decorating_function(user_function): @@ -709,7 +631,29 @@ * The "explicit early binding" variant may be applicable to the discussions on python-ideas on how to eliminate the default argument hack. A ``given`` - clause in the header line for functions may be the answer to that question. + clause in the header line for functions (after the return type annotation) + may be the answer to that question. + + +Rejected Alternatives +===================== + +* An earlier version of this PEP allowed implicit forward references to the + names in the trailing suite, and also used implicit early binding + semantics. Both of these ideas substantially complicated the proposal + without providing a sufficient increase in expressive power. The current + proposing with explicit forward references and early binding brings the + new construct into line with existing scoping semantics, greatly + improving the chances the idea can actually be implemented. + +* In addition to the proposals made here, there have also been suggestions + of two suite "in-order" variants which provide the limited scoping of + names without supporting out-of-order execution. I believe these + suggestions largely miss the point of what people are complaining about + when they ask for multi-line lambda support - it isn't that coming up + with a name for the subexpression is especially difficult, it's that + naming the function before the statement that uses it means the code + no longer matches the way the developer thinks about the problem at hand. Reference Implementation @@ -722,10 +666,10 @@ TO-DO ===== -* Mention two-suite in-order variants (and explain why they're even more - pointless than the specific idea in the PEP) * Mention PEP 359 and possible uses for locals() in the ``given`` clause +* Figure out if this can be used internally to make the implementation of + zero-argument super() calls less awful References ========== -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Sep 5 20:20:51 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 5 Sep 2012 20:20:51 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1ODQx?= =?utf-8?q?=3A_The_readable=28=29=2C_writable=28=29_and_seekable=28=29_met?= =?utf-8?q?hods_of_BytesIO?= Message-ID: <3XBtWl3b5kzPS8@mail.python.org> http://hg.python.org/cpython/rev/524931e5aebf changeset: 78852:524931e5aebf branch: 3.2 parent: 78848:c49f89261d65 user: Antoine Pitrou date: Wed Sep 05 20:11:49 2012 +0200 summary: Issue #15841: The readable(), writable() and seekable() methods of BytesIO and StringIO objects now raise ValueError when the object has been closed. Patch by Alessandro Moura. files: Lib/_pyio.py | 8 ++++++++ Lib/test/test_memoryio.py | 7 +++---- Misc/ACKS | 1 + Misc/NEWS | 4 ++++ Modules/_io/bytesio.c | 20 +++++++++++++++----- Modules/_io/stringio.c | 19 ++++++++++++++++--- 6 files changed, 47 insertions(+), 12 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -889,12 +889,18 @@ return pos def readable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True def writable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True @@ -1567,6 +1573,8 @@ return self._buffer def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return self._seekable def readable(self): diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -318,9 +318,9 @@ self.assertEqual(memio.isatty(), False) self.assertEqual(memio.closed, False) memio.close() - self.assertEqual(memio.writable(), True) - self.assertEqual(memio.readable(), True) - self.assertEqual(memio.seekable(), True) + self.assertRaises(ValueError, memio.writable) + self.assertRaises(ValueError, memio.readable) + self.assertRaises(ValueError, memio.seekable) self.assertRaises(ValueError, memio.isatty) self.assertEqual(memio.closed, True) @@ -665,7 +665,6 @@ check(io.BytesIO(b'a'), basesize + 1 + 1 ) check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 ) - class CStringIOTest(PyStringIOTest): ioclass = io.StringIO UnsupportedOperation = io.UnsupportedOperation diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -658,6 +658,7 @@ Paul Moore Derek Morr James A Morrison +Alessandro Moura Pablo Mouzo Mher Movsisyan Ruslan Mstoi diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -115,6 +115,10 @@ Library ------- +- Issue #15841: The readable(), writable() and seekable() methods of BytesIO + and StringIO objects now raise ValueError when the object has been closed. + Patch by Alessandro Moura. + - Issue #15509: webbrowser.UnixBrowser no longer passes empty arguments to Popen when %action substitutions produce empty strings. diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -121,7 +121,7 @@ } /* Internal routine for writing a string of bytes to the buffer of a BytesIO - object. Returns the number of bytes wrote, or -1 on error. */ + object. Returns the number of bytes written, or -1 on error. */ static Py_ssize_t write_bytes(bytesio *self, const char *bytes, Py_ssize_t len) { @@ -171,10 +171,20 @@ } } +PyDoc_STRVAR(readable_doc, +"readable() -> bool. Returns True if the IO object can be read."); + +PyDoc_STRVAR(writable_doc, +"writable() -> bool. Returns True if the IO object can be written."); + +PyDoc_STRVAR(seekable_doc, +"seekable() -> bool. Returns True if the IO object can be seeked."); + /* Generic getter for the writable, readable and seekable properties */ static PyObject * -return_true(bytesio *self) +return_not_closed(bytesio *self) { + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -867,9 +877,9 @@ }; static struct PyMethodDef bytesio_methods[] = { - {"readable", (PyCFunction)return_true, METH_NOARGS, NULL}, - {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL}, - {"writable", (PyCFunction)return_true, METH_NOARGS, NULL}, + {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc}, + {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc}, + {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc}, {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc}, {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc}, {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc}, diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -650,10 +650,21 @@ } /* Properties and pseudo-properties */ + +PyDoc_STRVAR(stringio_readable_doc, +"readable() -> bool. Returns True if the IO object can be read."); + +PyDoc_STRVAR(stringio_writable_doc, +"writable() -> bool. Returns True if the IO object can be written."); + +PyDoc_STRVAR(stringio_seekable_doc, +"seekable() -> bool. Returns True if the IO object can be seeked."); + static PyObject * stringio_seekable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -661,6 +672,7 @@ stringio_readable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -668,6 +680,7 @@ stringio_writable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -835,9 +848,9 @@ {"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc}, {"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc}, - {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS}, - {"readable", (PyCFunction)stringio_readable, METH_NOARGS}, - {"writable", (PyCFunction)stringio_writable, METH_NOARGS}, + {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc}, + {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc}, + {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc}, {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, {"__setstate__", (PyCFunction)stringio_setstate, METH_O}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 5 20:20:53 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 5 Sep 2012 20:20:53 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?b?KTogSXNzdWUgIzE1ODQxOiBUaGUgcmVhZGFibGUoKSwgd3JpdGFibGUoKSBh?= =?utf-8?q?nd_seekable=28=29_methods_of_BytesIO?= Message-ID: <3XBtWn1vyyzQJM@mail.python.org> http://hg.python.org/cpython/rev/fcf097cb5f6b changeset: 78853:fcf097cb5f6b parent: 78851:82ae284cd5f1 parent: 78852:524931e5aebf user: Antoine Pitrou date: Wed Sep 05 20:13:48 2012 +0200 summary: Issue #15841: The readable(), writable() and seekable() methods of BytesIO and StringIO objects now raise ValueError when the object has been closed. Patch by Alessandro Moura. files: Lib/_pyio.py | 8 ++++++++ Lib/test/test_memoryio.py | 7 +++---- Misc/ACKS | 1 + Misc/NEWS | 4 ++++ Modules/_io/bytesio.c | 20 +++++++++++++++----- Modules/_io/stringio.c | 19 ++++++++++++++++--- 6 files changed, 47 insertions(+), 12 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -895,12 +895,18 @@ return pos def readable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True def writable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True @@ -1562,6 +1568,8 @@ return self._buffer def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return self._seekable def readable(self): diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -318,9 +318,9 @@ self.assertEqual(memio.isatty(), False) self.assertEqual(memio.closed, False) memio.close() - self.assertEqual(memio.writable(), True) - self.assertEqual(memio.readable(), True) - self.assertEqual(memio.seekable(), True) + self.assertRaises(ValueError, memio.writable) + self.assertRaises(ValueError, memio.readable) + self.assertRaises(ValueError, memio.seekable) self.assertRaises(ValueError, memio.isatty) self.assertEqual(memio.closed, True) @@ -665,7 +665,6 @@ check(io.BytesIO(b'a'), basesize + 1 + 1 ) check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 ) - class CStringIOTest(PyStringIOTest): ioclass = io.StringIO UnsupportedOperation = io.UnsupportedOperation diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -731,6 +731,7 @@ Derek Morr James A Morrison Derek McTavish Mounce +Alessandro Moura Pablo Mouzo Mher Movsisyan Ruslan Mstoi diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,10 @@ Library ------- +- Issue #15841: The readable(), writable() and seekable() methods of BytesIO + and StringIO objects now raise ValueError when the object has been closed. + Patch by Alessandro Moura. + - Issue #15447: Use subprocess.DEVNULL in webbrowser, instead of opening os.devnull explicitly and leaving it open. diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -121,7 +121,7 @@ } /* Internal routine for writing a string of bytes to the buffer of a BytesIO - object. Returns the number of bytes wrote, or -1 on error. */ + object. Returns the number of bytes written, or -1 on error. */ static Py_ssize_t write_bytes(bytesio *self, const char *bytes, Py_ssize_t len) { @@ -171,10 +171,20 @@ } } +PyDoc_STRVAR(readable_doc, +"readable() -> bool. Returns True if the IO object can be read."); + +PyDoc_STRVAR(writable_doc, +"writable() -> bool. Returns True if the IO object can be written."); + +PyDoc_STRVAR(seekable_doc, +"seekable() -> bool. Returns True if the IO object can be seeked."); + /* Generic getter for the writable, readable and seekable properties */ static PyObject * -return_true(bytesio *self) +return_not_closed(bytesio *self) { + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -867,9 +877,9 @@ }; static struct PyMethodDef bytesio_methods[] = { - {"readable", (PyCFunction)return_true, METH_NOARGS, NULL}, - {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL}, - {"writable", (PyCFunction)return_true, METH_NOARGS, NULL}, + {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc}, + {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc}, + {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc}, {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc}, {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc}, {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc}, diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -760,10 +760,21 @@ } /* Properties and pseudo-properties */ + +PyDoc_STRVAR(stringio_readable_doc, +"readable() -> bool. Returns True if the IO object can be read."); + +PyDoc_STRVAR(stringio_writable_doc, +"writable() -> bool. Returns True if the IO object can be written."); + +PyDoc_STRVAR(stringio_seekable_doc, +"seekable() -> bool. Returns True if the IO object can be seeked."); + static PyObject * stringio_seekable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -771,6 +782,7 @@ stringio_readable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -778,6 +790,7 @@ stringio_writable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -956,9 +969,9 @@ {"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc}, {"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc}, - {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS}, - {"readable", (PyCFunction)stringio_readable, METH_NOARGS}, - {"writable", (PyCFunction)stringio_writable, METH_NOARGS}, + {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc}, + {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc}, + {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc}, {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, {"__setstate__", (PyCFunction)stringio_setstate, METH_O}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 5 20:20:54 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 5 Sep 2012 20:20:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1ODQx?= =?utf-8?q?=3A_The_readable=28=29=2C_writable=28=29_and_seekable=28=29_met?= =?utf-8?q?hods_of_io=2EBytesIO?= Message-ID: <3XBtWp6v9qzQLW@mail.python.org> http://hg.python.org/cpython/rev/d0ab34d4c733 changeset: 78854:d0ab34d4c733 branch: 2.7 parent: 78826:2370e331241b user: Antoine Pitrou date: Wed Sep 05 20:11:49 2012 +0200 summary: Issue #15841: The readable(), writable() and seekable() methods of io.BytesIO and io.StringIO objects now raise ValueError when the object has been closed. Patch by Alessandro Moura. files: Lib/_pyio.py | 8 ++++++++ Lib/test/test_memoryio.py | 7 +++---- Misc/ACKS | 1 + Misc/NEWS | 4 ++++ Modules/_io/bytesio.c | 20 +++++++++++++++----- Modules/_io/stringio.c | 19 ++++++++++++++++--- 6 files changed, 47 insertions(+), 12 deletions(-) diff --git a/Lib/_pyio.py b/Lib/_pyio.py --- a/Lib/_pyio.py +++ b/Lib/_pyio.py @@ -883,12 +883,18 @@ return pos def readable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True def writable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return True @@ -1546,6 +1552,8 @@ return self._buffer def seekable(self): + if self.closed: + raise ValueError("I/O operation on closed file.") return self._seekable def readable(self): diff --git a/Lib/test/test_memoryio.py b/Lib/test/test_memoryio.py --- a/Lib/test/test_memoryio.py +++ b/Lib/test/test_memoryio.py @@ -328,9 +328,9 @@ self.assertEqual(memio.isatty(), False) self.assertEqual(memio.closed, False) memio.close() - self.assertEqual(memio.writable(), True) - self.assertEqual(memio.readable(), True) - self.assertEqual(memio.seekable(), True) + self.assertRaises(ValueError, memio.writable) + self.assertRaises(ValueError, memio.readable) + self.assertRaises(ValueError, memio.seekable) self.assertRaises(ValueError, memio.isatty) self.assertEqual(memio.closed, True) @@ -649,7 +649,6 @@ check(io.BytesIO(b'a'), basesize + 1 + 1 ) check(io.BytesIO(b'a' * 1000), basesize + 1000 + 1 ) - class CStringIOTest(PyStringIOTest): ioclass = io.StringIO UnsupportedOperation = io.UnsupportedOperation diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -602,6 +602,7 @@ Paul Moore Derek Morr James A Morrison +Alessandro Moura Pablo Mouzo Ruslan Mstoi Sjoerd Mullender diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -98,6 +98,10 @@ Library ------- +- Issue #15841: The readable(), writable() and seekable() methods of + io.BytesIO and io.StringIO objects now raise ValueError when the object has + been closed. Patch by Alessandro Moura. + - Issue #12776,#11839: call argparse type function (specified by add_argument) only once. Before, the type function was called twice in the case where the default was specified and the argument was given as well. This was diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -106,7 +106,7 @@ } /* Internal routine for writing a string of bytes to the buffer of a BytesIO - object. Returns the number of bytes wrote, or -1 on error. */ + object. Returns the number of bytes written, or -1 on error. */ static Py_ssize_t write_bytes(bytesio *self, const char *bytes, Py_ssize_t len) { @@ -156,10 +156,20 @@ } } +PyDoc_STRVAR(readable_doc, +"readable() -> bool. Returns True if the IO object can be read."); + +PyDoc_STRVAR(writable_doc, +"writable() -> bool. Returns True if the IO object can be written."); + +PyDoc_STRVAR(seekable_doc, +"seekable() -> bool. Returns True if the IO object can be seeked."); + /* Generic getter for the writable, readable and seekable properties */ static PyObject * -return_true(bytesio *self) +return_not_closed(bytesio *self) { + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -827,9 +837,9 @@ }; static struct PyMethodDef bytesio_methods[] = { - {"readable", (PyCFunction)return_true, METH_NOARGS, NULL}, - {"seekable", (PyCFunction)return_true, METH_NOARGS, NULL}, - {"writable", (PyCFunction)return_true, METH_NOARGS, NULL}, + {"readable", (PyCFunction)return_not_closed, METH_NOARGS, readable_doc}, + {"seekable", (PyCFunction)return_not_closed, METH_NOARGS, seekable_doc}, + {"writable", (PyCFunction)return_not_closed, METH_NOARGS, writable_doc}, {"close", (PyCFunction)bytesio_close, METH_NOARGS, close_doc}, {"flush", (PyCFunction)bytesio_flush, METH_NOARGS, flush_doc}, {"isatty", (PyCFunction)bytesio_isatty, METH_NOARGS, isatty_doc}, diff --git a/Modules/_io/stringio.c b/Modules/_io/stringio.c --- a/Modules/_io/stringio.c +++ b/Modules/_io/stringio.c @@ -632,10 +632,21 @@ } /* Properties and pseudo-properties */ + +PyDoc_STRVAR(stringio_readable_doc, +"readable() -> bool. Returns True if the IO object can be read."); + +PyDoc_STRVAR(stringio_writable_doc, +"writable() -> bool. Returns True if the IO object can be written."); + +PyDoc_STRVAR(stringio_seekable_doc, +"seekable() -> bool. Returns True if the IO object can be seeked."); + static PyObject * stringio_seekable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -643,6 +654,7 @@ stringio_readable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -650,6 +662,7 @@ stringio_writable(stringio *self, PyObject *args) { CHECK_INITIALIZED(self); + CHECK_CLOSED(self); Py_RETURN_TRUE; } @@ -817,9 +830,9 @@ {"seek", (PyCFunction)stringio_seek, METH_VARARGS, stringio_seek_doc}, {"write", (PyCFunction)stringio_write, METH_O, stringio_write_doc}, - {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS}, - {"readable", (PyCFunction)stringio_readable, METH_NOARGS}, - {"writable", (PyCFunction)stringio_writable, METH_NOARGS}, + {"seekable", (PyCFunction)stringio_seekable, METH_NOARGS, stringio_seekable_doc}, + {"readable", (PyCFunction)stringio_readable, METH_NOARGS, stringio_readable_doc}, + {"writable", (PyCFunction)stringio_writable, METH_NOARGS, stringio_writable_doc}, {"__getstate__", (PyCFunction)stringio_getstate, METH_NOARGS}, {"__setstate__", (PyCFunction)stringio_setstate, METH_O}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 01:03:50 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 6 Sep 2012 01:03:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEzOTky?= =?utf-8?q?=3A_The_trashcan_mechanism_is_now_thread-safe=2E__This_eliminat?= =?utf-8?q?es?= Message-ID: <3XC0pG20KWzQM6@mail.python.org> http://hg.python.org/cpython/rev/5a2ef447b80d changeset: 78855:5a2ef447b80d branch: 2.7 user: Antoine Pitrou date: Thu Sep 06 00:59:49 2012 +0200 summary: Issue #13992: The trashcan mechanism is now thread-safe. This eliminates sporadic crashes in multi-thread programs when several long deallocator chains ran concurrently and involved subclasses of built-in container types. Because of this change, a couple extension modules compiled for 2.7.4 (those which use the trashcan mechanism, despite it being undocumented) will not be loadable by 2.7.3 and earlier. However, extension modules compiled for 2.7.3 and earlier will be loadable by 2.7.4. files: Include/object.h | 27 ++++++++---- Include/pystate.h | 3 + Lib/test/test_gc.py | 69 ++++++++++++++++++++++++++++++++ Misc/NEWS | 5 ++ Objects/object.c | 37 +++++++++++++++++ Objects/typeobject.c | 5 ++ Python/pystate.c | 3 + 7 files changed, 140 insertions(+), 9 deletions(-) diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -971,24 +971,33 @@ with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL. */ +/* This is the old private API, invoked by the macros before 2.7.4. + Kept for binary compatibility of extensions. */ PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*); PyAPI_FUNC(void) _PyTrash_destroy_chain(void); PyAPI_DATA(int) _PyTrash_delete_nesting; PyAPI_DATA(PyObject *) _PyTrash_delete_later; +/* The new thread-safe private API, invoked by the macros below. */ +PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*); +PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void); + #define PyTrash_UNWIND_LEVEL 50 #define Py_TRASHCAN_SAFE_BEGIN(op) \ - if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ - ++_PyTrash_delete_nesting; - /* The body of the deallocator is here. */ + do { \ + PyThreadState *_tstate = PyThreadState_GET(); \ + if (_tstate->trash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ + ++_tstate->trash_delete_nesting; + /* The body of the deallocator is here. */ #define Py_TRASHCAN_SAFE_END(op) \ - --_PyTrash_delete_nesting; \ - if (_PyTrash_delete_later && _PyTrash_delete_nesting <= 0) \ - _PyTrash_destroy_chain(); \ - } \ - else \ - _PyTrash_deposit_object((PyObject*)op); + --_tstate->trash_delete_nesting; \ + if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \ + _PyTrash_thread_destroy_chain(); \ + } \ + else \ + _PyTrash_thread_deposit_object((PyObject*)op); \ + } while (0); #ifdef __cplusplus } diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -95,6 +95,9 @@ PyObject *async_exc; /* Asynchronous exception to raise */ long thread_id; /* Thread id where this tstate was created */ + int trash_delete_nesting; + PyObject *trash_delete_later; + /* XXX signal handlers should also be here */ } PyThreadState; diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1,9 +1,15 @@ import unittest from test.test_support import verbose, run_unittest import sys +import time import gc import weakref +try: + import threading +except ImportError: + threading = None + ### Support code ############################################################################### @@ -299,6 +305,69 @@ v = {1: v, 2: Ouch()} gc.disable() + @unittest.skipUnless(threading, "test meaningless on builds without threads") + def test_trashcan_threads(self): + # Issue #13992: trashcan mechanism should be thread-safe + NESTING = 60 + N_THREADS = 2 + + def sleeper_gen(): + """A generator that releases the GIL when closed or dealloc'ed.""" + try: + yield + finally: + time.sleep(0.000001) + + class C(list): + # Appending to a list is atomic, which avoids the use of a lock. + inits = [] + dels = [] + def __init__(self, alist): + self[:] = alist + C.inits.append(None) + def __del__(self): + # This __del__ is called by subtype_dealloc(). + C.dels.append(None) + # `g` will release the GIL when garbage-collected. This + # helps assert subtype_dealloc's behaviour when threads + # switch in the middle of it. + g = sleeper_gen() + next(g) + # Now that __del__ is finished, subtype_dealloc will proceed + # to call list_dealloc, which also uses the trashcan mechanism. + + def make_nested(): + """Create a sufficiently nested container object so that the + trashcan mechanism is invoked when deallocating it.""" + x = C([]) + for i in range(NESTING): + x = [C([x])] + del x + + def run_thread(): + """Exercise make_nested() in a loop.""" + while not exit: + make_nested() + + old_checkinterval = sys.getcheckinterval() + sys.setcheckinterval(3) + try: + exit = False + threads = [] + for i in range(N_THREADS): + t = threading.Thread(target=run_thread) + threads.append(t) + for t in threads: + t.start() + time.sleep(1.0) + exit = True + for t in threads: + t.join() + finally: + sys.setcheckinterval(old_checkinterval) + gc.collect() + self.assertEqual(len(C.inits), len(C.dels)) + def test_boom(self): class Boom: def __getattr__(self, someattribute): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,11 @@ Core and Builtins ----------------- +- Issue #13992: The trashcan mechanism is now thread-safe. This eliminates + sporadic crashes in multi-thread programs when several long deallocator + chains ran concurrently and involved subclasses of built-in container + types. + - Issue #15801: Make sure mappings passed to '%' formatting are actually subscriptable. diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -2428,6 +2428,18 @@ _PyTrash_delete_later = op; } +/* The equivalent API, using per-thread state recursion info */ +void +_PyTrash_thread_deposit_object(PyObject *op) +{ + PyThreadState *tstate = PyThreadState_GET(); + assert(PyObject_IS_GC(op)); + assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED); + assert(op->ob_refcnt == 0); + _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *) tstate->trash_delete_later; + tstate->trash_delete_later = op; +} + /* Dealloccate all the objects in the _PyTrash_delete_later list. Called when * the call-stack unwinds again. */ @@ -2454,6 +2466,31 @@ } } +/* The equivalent API, using per-thread state recursion info */ +void +_PyTrash_thread_destroy_chain(void) +{ + PyThreadState *tstate = PyThreadState_GET(); + while (tstate->trash_delete_later) { + PyObject *op = tstate->trash_delete_later; + destructor dealloc = Py_TYPE(op)->tp_dealloc; + + tstate->trash_delete_later = + (PyObject*) _Py_AS_GC(op)->gc.gc_prev; + + /* Call the deallocator directly. This used to try to + * fool Py_DECREF into calling it indirectly, but + * Py_DECREF was already called on this object, and in + * assorted non-release builds calling Py_DECREF again ends + * up distorting allocation statistics. + */ + assert(op->ob_refcnt == 0); + ++tstate->trash_delete_nesting; + (*dealloc)(op); + --tstate->trash_delete_nesting; + } +} + #ifdef __cplusplus } #endif diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -896,6 +896,7 @@ { PyTypeObject *type, *base; destructor basedealloc; + PyThreadState *tstate = PyThreadState_GET(); /* Extract the type; we expect it to be a heap type */ type = Py_TYPE(self); @@ -945,8 +946,10 @@ /* See explanation at end of function for full disclosure */ PyObject_GC_UnTrack(self); ++_PyTrash_delete_nesting; + ++ tstate->trash_delete_nesting; Py_TRASHCAN_SAFE_BEGIN(self); --_PyTrash_delete_nesting; + -- tstate->trash_delete_nesting; /* DO NOT restore GC tracking at this point. weakref callbacks * (if any, and whether directly here or indirectly in something we * call) may trigger GC, and if self is tracked at that point, it @@ -1025,8 +1028,10 @@ endlabel: ++_PyTrash_delete_nesting; + ++ tstate->trash_delete_nesting; Py_TRASHCAN_SAFE_END(self); --_PyTrash_delete_nesting; + -- tstate->trash_delete_nesting; /* Explanation of the weirdness around the trashcan macros: diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -192,6 +192,9 @@ tstate->c_profileobj = NULL; tstate->c_traceobj = NULL; + tstate->trash_delete_nesting = 0; + tstate->trash_delete_later = NULL; + if (init) _PyThreadState_Init(tstate); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 01:21:42 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 6 Sep 2012 01:21:42 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEzOTky?= =?utf-8?q?=3A_The_trashcan_mechanism_is_now_thread-safe=2E__This_eliminat?= =?utf-8?q?es?= Message-ID: <3XC1Bt5WrTzQM6@mail.python.org> http://hg.python.org/cpython/rev/e72cda3f40a2 changeset: 78856:e72cda3f40a2 branch: 3.2 parent: 78852:524931e5aebf user: Antoine Pitrou date: Thu Sep 06 00:59:49 2012 +0200 summary: Issue #13992: The trashcan mechanism is now thread-safe. This eliminates sporadic crashes in multi-thread programs when several long deallocator chains ran concurrently and involved subclasses of built-in container types. Because of this change, a couple extension modules compiled for 3.2.4 (those which use the trashcan mechanism, despite it being undocumented) will not be loadable by 3.2.3 and earlier. However, extension modules compiled for 3.2.3 and earlier will be loadable by 3.2.4. files: Include/object.h | 27 ++++++++---- Include/pystate.h | 3 + Lib/test/test_gc.py | 69 ++++++++++++++++++++++++++++++++ Misc/NEWS | 5 ++ Objects/object.c | 37 +++++++++++++++++ Objects/typeobject.c | 5 ++ Python/pystate.c | 3 + 7 files changed, 140 insertions(+), 9 deletions(-) diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -911,24 +911,33 @@ with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL. */ +/* This is the old private API, invoked by the macros before 3.2.4. + Kept for binary compatibility of extensions. */ PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*); PyAPI_FUNC(void) _PyTrash_destroy_chain(void); PyAPI_DATA(int) _PyTrash_delete_nesting; PyAPI_DATA(PyObject *) _PyTrash_delete_later; +/* The new thread-safe private API, invoked by the macros below. */ +PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*); +PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void); + #define PyTrash_UNWIND_LEVEL 50 #define Py_TRASHCAN_SAFE_BEGIN(op) \ - if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ - ++_PyTrash_delete_nesting; - /* The body of the deallocator is here. */ + do { \ + PyThreadState *_tstate = PyThreadState_GET(); \ + if (_tstate->trash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ + ++_tstate->trash_delete_nesting; + /* The body of the deallocator is here. */ #define Py_TRASHCAN_SAFE_END(op) \ - --_PyTrash_delete_nesting; \ - if (_PyTrash_delete_later && _PyTrash_delete_nesting <= 0) \ - _PyTrash_destroy_chain(); \ - } \ - else \ - _PyTrash_deposit_object((PyObject*)op); + --_tstate->trash_delete_nesting; \ + if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \ + _PyTrash_thread_destroy_chain(); \ + } \ + else \ + _PyTrash_thread_deposit_object((PyObject*)op); \ + } while (0); #ifdef __cplusplus } diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -113,6 +113,9 @@ PyObject *async_exc; /* Asynchronous exception to raise */ long thread_id; /* Thread id where this tstate was created */ + int trash_delete_nesting; + PyObject *trash_delete_later; + /* XXX signal handlers should also be here */ } PyThreadState; diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -1,9 +1,15 @@ import unittest from test.support import verbose, run_unittest, strip_python_stderr import sys +import time import gc import weakref +try: + import threading +except ImportError: + threading = None + ### Support code ############################################################################### @@ -310,6 +316,69 @@ v = {1: v, 2: Ouch()} gc.disable() + @unittest.skipUnless(threading, "test meaningless on builds without threads") + def test_trashcan_threads(self): + # Issue #13992: trashcan mechanism should be thread-safe + NESTING = 60 + N_THREADS = 2 + + def sleeper_gen(): + """A generator that releases the GIL when closed or dealloc'ed.""" + try: + yield + finally: + time.sleep(0.000001) + + class C(list): + # Appending to a list is atomic, which avoids the use of a lock. + inits = [] + dels = [] + def __init__(self, alist): + self[:] = alist + C.inits.append(None) + def __del__(self): + # This __del__ is called by subtype_dealloc(). + C.dels.append(None) + # `g` will release the GIL when garbage-collected. This + # helps assert subtype_dealloc's behaviour when threads + # switch in the middle of it. + g = sleeper_gen() + next(g) + # Now that __del__ is finished, subtype_dealloc will proceed + # to call list_dealloc, which also uses the trashcan mechanism. + + def make_nested(): + """Create a sufficiently nested container object so that the + trashcan mechanism is invoked when deallocating it.""" + x = C([]) + for i in range(NESTING): + x = [C([x])] + del x + + def run_thread(): + """Exercise make_nested() in a loop.""" + while not exit: + make_nested() + + old_switchinterval = sys.getswitchinterval() + sys.setswitchinterval(1e-5) + try: + exit = False + threads = [] + for i in range(N_THREADS): + t = threading.Thread(target=run_thread) + threads.append(t) + for t in threads: + t.start() + time.sleep(1.0) + exit = True + for t in threads: + t.join() + finally: + sys.setswitchinterval(old_switchinterval) + gc.collect() + self.assertEqual(len(C.inits), len(C.dels)) + def test_boom(self): class Boom: def __getattr__(self, someattribute): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ Core and Builtins ----------------- +- Issue #13992: The trashcan mechanism is now thread-safe. This eliminates + sporadic crashes in multi-thread programs when several long deallocator + chains ran concurrently and involved subclasses of built-in container + types. + - Issue #15846: Fix SystemError which happened when using ast.parse in an exception handler on code with syntax errors. diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1876,6 +1876,18 @@ _PyTrash_delete_later = op; } +/* The equivalent API, using per-thread state recursion info */ +void +_PyTrash_thread_deposit_object(PyObject *op) +{ + PyThreadState *tstate = PyThreadState_GET(); + assert(PyObject_IS_GC(op)); + assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED); + assert(op->ob_refcnt == 0); + _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *) tstate->trash_delete_later; + tstate->trash_delete_later = op; +} + /* Dealloccate all the objects in the _PyTrash_delete_later list. Called when * the call-stack unwinds again. */ @@ -1902,6 +1914,31 @@ } } +/* The equivalent API, using per-thread state recursion info */ +void +_PyTrash_thread_destroy_chain(void) +{ + PyThreadState *tstate = PyThreadState_GET(); + while (tstate->trash_delete_later) { + PyObject *op = tstate->trash_delete_later; + destructor dealloc = Py_TYPE(op)->tp_dealloc; + + tstate->trash_delete_later = + (PyObject*) _Py_AS_GC(op)->gc.gc_prev; + + /* Call the deallocator directly. This used to try to + * fool Py_DECREF into calling it indirectly, but + * Py_DECREF was already called on this object, and in + * assorted non-release builds calling Py_DECREF again ends + * up distorting allocation statistics. + */ + assert(op->ob_refcnt == 0); + ++tstate->trash_delete_nesting; + (*dealloc)(op); + --tstate->trash_delete_nesting; + } +} + #ifndef Py_TRACE_REFS /* For Py_LIMITED_API, we need an out-of-line version of _Py_Dealloc. Define this here, so we can undefine the macro. */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -847,6 +847,7 @@ { PyTypeObject *type, *base; destructor basedealloc; + PyThreadState *tstate = PyThreadState_GET(); /* Extract the type; we expect it to be a heap type */ type = Py_TYPE(self); @@ -896,8 +897,10 @@ /* See explanation at end of function for full disclosure */ PyObject_GC_UnTrack(self); ++_PyTrash_delete_nesting; + ++ tstate->trash_delete_nesting; Py_TRASHCAN_SAFE_BEGIN(self); --_PyTrash_delete_nesting; + -- tstate->trash_delete_nesting; /* DO NOT restore GC tracking at this point. weakref callbacks * (if any, and whether directly here or indirectly in something we * call) may trigger GC, and if self is tracked at that point, it @@ -976,8 +979,10 @@ endlabel: ++_PyTrash_delete_nesting; + ++ tstate->trash_delete_nesting; Py_TRASHCAN_SAFE_END(self); --_PyTrash_delete_nesting; + -- tstate->trash_delete_nesting; /* Explanation of the weirdness around the trashcan macros: diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -206,6 +206,9 @@ tstate->c_profileobj = NULL; tstate->c_traceobj = NULL; + tstate->trash_delete_nesting = 0; + tstate->trash_delete_later = NULL; + if (init) _PyThreadState_Init(tstate); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 01:21:44 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 6 Sep 2012 01:21:44 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2313992=3A_The_trashcan_mechanism_is_now_thread-s?= =?utf-8?q?afe=2E__This_eliminates?= Message-ID: <3XC1Bw5Q1VzQPN@mail.python.org> http://hg.python.org/cpython/rev/6bcaba9e8df2 changeset: 78857:6bcaba9e8df2 parent: 78853:fcf097cb5f6b parent: 78856:e72cda3f40a2 user: Antoine Pitrou date: Thu Sep 06 01:17:42 2012 +0200 summary: Issue #13992: The trashcan mechanism is now thread-safe. This eliminates sporadic crashes in multi-thread programs when several long deallocator chains ran concurrently and involved subclasses of built-in container types. Note that the trashcan functions are part of the stable ABI, therefore they have to be kept around for binary compatibility of extensions. files: Include/object.h | 27 ++++++++---- Include/pystate.h | 3 + Lib/test/test_gc.py | 69 ++++++++++++++++++++++++++++++++ Misc/NEWS | 5 ++ Objects/object.c | 37 +++++++++++++++++ Objects/typeobject.c | 5 ++ Python/pystate.c | 3 + 7 files changed, 140 insertions(+), 9 deletions(-) diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -961,24 +961,33 @@ with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL. */ +/* This is the old private API, invoked by the macros before 3.2.4. + Kept for binary compatibility of extensions using the stable ABI. */ PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*); PyAPI_FUNC(void) _PyTrash_destroy_chain(void); PyAPI_DATA(int) _PyTrash_delete_nesting; PyAPI_DATA(PyObject *) _PyTrash_delete_later; +/* The new thread-safe private API, invoked by the macros below. */ +PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*); +PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void); + #define PyTrash_UNWIND_LEVEL 50 #define Py_TRASHCAN_SAFE_BEGIN(op) \ - if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ - ++_PyTrash_delete_nesting; - /* The body of the deallocator is here. */ + do { \ + PyThreadState *_tstate = PyThreadState_GET(); \ + if (_tstate->trash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ + ++_tstate->trash_delete_nesting; + /* The body of the deallocator is here. */ #define Py_TRASHCAN_SAFE_END(op) \ - --_PyTrash_delete_nesting; \ - if (_PyTrash_delete_later && _PyTrash_delete_nesting <= 0) \ - _PyTrash_destroy_chain(); \ - } \ - else \ - _PyTrash_deposit_object((PyObject*)op); + --_tstate->trash_delete_nesting; \ + if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \ + _PyTrash_thread_destroy_chain(); \ + } \ + else \ + _PyTrash_thread_deposit_object((PyObject*)op); \ + } while (0); #ifndef Py_LIMITED_API PyAPI_FUNC(void) diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -114,6 +114,9 @@ PyObject *async_exc; /* Asynchronous exception to raise */ long thread_id; /* Thread id where this tstate was created */ + int trash_delete_nesting; + PyObject *trash_delete_later; + /* XXX signal handlers should also be here */ } PyThreadState; diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -2,9 +2,15 @@ from test.support import (verbose, refcount_test, run_unittest, strip_python_stderr) import sys +import time import gc import weakref +try: + import threading +except ImportError: + threading = None + ### Support code ############################################################################### @@ -328,6 +334,69 @@ v = {1: v, 2: Ouch()} gc.disable() + @unittest.skipUnless(threading, "test meaningless on builds without threads") + def test_trashcan_threads(self): + # Issue #13992: trashcan mechanism should be thread-safe + NESTING = 60 + N_THREADS = 2 + + def sleeper_gen(): + """A generator that releases the GIL when closed or dealloc'ed.""" + try: + yield + finally: + time.sleep(0.000001) + + class C(list): + # Appending to a list is atomic, which avoids the use of a lock. + inits = [] + dels = [] + def __init__(self, alist): + self[:] = alist + C.inits.append(None) + def __del__(self): + # This __del__ is called by subtype_dealloc(). + C.dels.append(None) + # `g` will release the GIL when garbage-collected. This + # helps assert subtype_dealloc's behaviour when threads + # switch in the middle of it. + g = sleeper_gen() + next(g) + # Now that __del__ is finished, subtype_dealloc will proceed + # to call list_dealloc, which also uses the trashcan mechanism. + + def make_nested(): + """Create a sufficiently nested container object so that the + trashcan mechanism is invoked when deallocating it.""" + x = C([]) + for i in range(NESTING): + x = [C([x])] + del x + + def run_thread(): + """Exercise make_nested() in a loop.""" + while not exit: + make_nested() + + old_switchinterval = sys.getswitchinterval() + sys.setswitchinterval(1e-5) + try: + exit = False + threads = [] + for i in range(N_THREADS): + t = threading.Thread(target=run_thread) + threads.append(t) + for t in threads: + t.start() + time.sleep(1.0) + exit = True + for t in threads: + t.join() + finally: + sys.setswitchinterval(old_switchinterval) + gc.collect() + self.assertEqual(len(C.inits), len(C.dels)) + def test_boom(self): class Boom: def __getattr__(self, someattribute): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ Core and Builtins ----------------- +- Issue #13992: The trashcan mechanism is now thread-safe. This eliminates + sporadic crashes in multi-thread programs when several long deallocator + chains ran concurrently and involved subclasses of built-in container + types. + - Issue #15839: Convert SystemErrors in super() to RuntimeErrors. - Issue #15846: Fix SystemError which happened when using ast.parse in an diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1954,6 +1954,18 @@ _PyTrash_delete_later = op; } +/* The equivalent API, using per-thread state recursion info */ +void +_PyTrash_thread_deposit_object(PyObject *op) +{ + PyThreadState *tstate = PyThreadState_GET(); + assert(PyObject_IS_GC(op)); + assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED); + assert(op->ob_refcnt == 0); + _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *) tstate->trash_delete_later; + tstate->trash_delete_later = op; +} + /* Dealloccate all the objects in the _PyTrash_delete_later list. Called when * the call-stack unwinds again. */ @@ -1980,6 +1992,31 @@ } } +/* The equivalent API, using per-thread state recursion info */ +void +_PyTrash_thread_destroy_chain(void) +{ + PyThreadState *tstate = PyThreadState_GET(); + while (tstate->trash_delete_later) { + PyObject *op = tstate->trash_delete_later; + destructor dealloc = Py_TYPE(op)->tp_dealloc; + + tstate->trash_delete_later = + (PyObject*) _Py_AS_GC(op)->gc.gc_prev; + + /* Call the deallocator directly. This used to try to + * fool Py_DECREF into calling it indirectly, but + * Py_DECREF was already called on this object, and in + * assorted non-release builds calling Py_DECREF again ends + * up distorting allocation statistics. + */ + assert(op->ob_refcnt == 0); + ++tstate->trash_delete_nesting; + (*dealloc)(op); + --tstate->trash_delete_nesting; + } +} + #ifndef Py_TRACE_REFS /* For Py_LIMITED_API, we need an out-of-line version of _Py_Dealloc. Define this here, so we can undefine the macro. */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -891,6 +891,7 @@ { PyTypeObject *type, *base; destructor basedealloc; + PyThreadState *tstate = PyThreadState_GET(); /* Extract the type; we expect it to be a heap type */ type = Py_TYPE(self); @@ -940,8 +941,10 @@ /* See explanation at end of function for full disclosure */ PyObject_GC_UnTrack(self); ++_PyTrash_delete_nesting; + ++ tstate->trash_delete_nesting; Py_TRASHCAN_SAFE_BEGIN(self); --_PyTrash_delete_nesting; + -- tstate->trash_delete_nesting; /* DO NOT restore GC tracking at this point. weakref callbacks * (if any, and whether directly here or indirectly in something we * call) may trigger GC, and if self is tracked at that point, it @@ -1020,8 +1023,10 @@ endlabel: ++_PyTrash_delete_nesting; + ++ tstate->trash_delete_nesting; Py_TRASHCAN_SAFE_END(self); --_PyTrash_delete_nesting; + -- tstate->trash_delete_nesting; /* Explanation of the weirdness around the trashcan macros: diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -206,6 +206,9 @@ tstate->c_profileobj = NULL; tstate->c_traceobj = NULL; + tstate->trash_delete_nesting = 0; + tstate->trash_delete_later = NULL; + if (init) _PyThreadState_Init(tstate); -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Sep 6 06:06:46 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 06 Sep 2012 06:06:46 +0200 Subject: [Python-checkins] Daily reference leaks (6bcaba9e8df2): sum=1 Message-ID: results for 6bcaba9e8df2 on branch "default" -------------------------------------------- test_support leaked [1, 0, 0] references, sum=1 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogebcnjc', '-x'] From python-checkins at python.org Thu Sep 6 07:21:53 2012 From: python-checkins at python.org (eric.snow) Date: Thu, 6 Sep 2012 07:21:53 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_add_whatsnew_entry_for_PEP?= =?utf-8?q?_421?= Message-ID: <3XC9BT1kLczQMw@mail.python.org> http://hg.python.org/cpython/rev/30ce5a944c7d changeset: 78858:30ce5a944c7d user: Eric Snow date: Wed Sep 05 22:19:38 2012 -0700 summary: add whatsnew entry for PEP 421 files: Doc/whatsnew/3.3.rst | 35 ++++++++++++++++++++++++++++++++ 1 files changed, 35 insertions(+), 0 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -564,6 +564,41 @@ or amends calling signatures or arguments. +PEP 421: Adding sys.implementation +================================== + +:pep:`421` - Adding sys.implementation + PEP written and implemented by Eric Snow. + +A new attribute on the :mod:`sys` module exposes details specific to the +implementation of the currently running interpreter. The initial set of +attributes on :attr:`sys.implementation` are ``name``, ``version``, +``hexversion``, and ``cache_tag``. + +The intention of ``sys.implementation`` is to consolidate into one namespace +the implementation-specific data used by the standard library. This allows +different Python implementations to share a single standard library code base +much more easily. In its initial state, ``sys.implementation`` holds only a +small portion of the implementation-specific data. Over time that ratio will +shift in order to make the standard library more portable. + +One example of improved standard library portability is ``cache_tag``. As of +Python 3.3, ``sys.implementation.cache_tag`` is used by :mod:`importlib` to +support :pep:`3147` compliance. Any Python implementation that uses +``importlib`` for its built-in import system may use ``cache_tag`` to control +the caching behavior for modules. + +SimpleNamespace +--------------- + +The implementation of ``sys.implementation`` also introduces a new type to +Python: :class:`types.SimpleNamespace`. In contrast to a mapping-based +namespace, like :class:`dict`, ``SimpleNamespace`` is attribute-based, like +:class:`object`. However, unlike ``object``, ``SimpleNamespace`` instances +are writable. This means that you can add, remove, and modify the namespace +through normal attribute access. + + .. _importlib: Using importlib as the Implementation of Import -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 09:49:19 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 6 Sep 2012 09:49:19 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=5Ftestbuffer=2Ec=3A_In_al?= =?utf-8?q?l_current_use_cases_of_cmp=5Fstructure=28=29_dest-=3Eformat_and?= Message-ID: <3XCDSb3qZFzQNv@mail.python.org> http://hg.python.org/cpython/rev/7c007110d952 changeset: 78859:7c007110d952 user: Stefan Krah date: Thu Sep 06 09:42:29 2012 +0200 summary: _testbuffer.c: In all current use cases of cmp_structure() dest->format and src->format are either both NULL or both non-NULL. However, it is safer to generalize the function. Found by Coverity. files: Modules/_testbuffer.c | 7 +++---- 1 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Modules/_testbuffer.c b/Modules/_testbuffer.c --- a/Modules/_testbuffer.c +++ b/Modules/_testbuffer.c @@ -16,6 +16,7 @@ static const char *simple_fmt = "B"; PyObject *simple_format = NULL; #define SIMPLE_FORMAT(fmt) (fmt == NULL || strcmp(fmt, "B") == 0) +#define FIX_FORMAT(fmt) (fmt == NULL ? "B" : fmt) /**************************************************************************/ @@ -513,10 +514,8 @@ cmp_structure(Py_buffer *dest, Py_buffer *src) { Py_ssize_t i; - int same_fmt = ((dest->format == NULL && src->format == NULL) || \ - (strcmp(dest->format, src->format) == 0)); - - if (!same_fmt || + + if (strcmp(FIX_FORMAT(dest->format), FIX_FORMAT(src->format)) != 0 || dest->itemsize != src->itemsize || dest->ndim != src->ndim) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 13:09:21 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 6 Sep 2012 13:09:21 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_After_the_jump_in_line_105?= =?utf-8?q?1_unicode=5Ftmp_is_NULL=2E_Found_by_Coverity=2E?= Message-ID: <3XCJvP5V0CzQLq@mail.python.org> http://hg.python.org/cpython/rev/dc2909a62262 changeset: 78860:dc2909a62262 user: Stefan Krah date: Thu Sep 06 13:02:46 2012 +0200 summary: After the jump in line 1051 unicode_tmp is NULL. Found by Coverity. files: Python/formatter_unicode.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Python/formatter_unicode.c b/Python/formatter_unicode.c --- a/Python/formatter_unicode.c +++ b/Python/formatter_unicode.c @@ -1099,7 +1099,7 @@ &locale, 0); done: - Py_DECREF(unicode_tmp); + Py_XDECREF(unicode_tmp); free_locale_info(&locale); return result; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 18:06:55 2012 From: python-checkins at python.org (christian.heimes) Date: Thu, 6 Sep 2012 18:06:55 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1NTkx?= =?utf-8?q?=3A_run_ctypes=27_configure_in_quiet_mode_when_setup=2Epy_runs_?= =?utf-8?q?silently?= Message-ID: <3XCRVl4l9dzNB3@mail.python.org> http://hg.python.org/cpython/rev/048e13546a7c changeset: 78861:048e13546a7c branch: 3.2 parent: 78856:e72cda3f40a2 user: Christian Heimes date: Thu Sep 06 18:02:49 2012 +0200 summary: Issue #15591: run ctypes' configure in quiet mode when setup.py runs silently files: setup.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1675,6 +1675,8 @@ from distutils.dir_util import mkpath mkpath(ffi_builddir) config_args = [] + if not self.verbose: + config_args.append("-q") # Pass empty CFLAGS because we'll just append the resulting # CFLAGS to Python's; -g or -O2 is to be avoided. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 18:06:57 2012 From: python-checkins at python.org (christian.heimes) Date: Thu, 6 Sep 2012 18:06:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315591=3A_run_ctypes=27_configure_in_quiet_mode_?= =?utf-8?q?when_setup=2Epy_runs_silently?= Message-ID: <3XCRVn3DyNzQYc@mail.python.org> http://hg.python.org/cpython/rev/e5569b03a287 changeset: 78862:e5569b03a287 parent: 78860:dc2909a62262 parent: 78861:048e13546a7c user: Christian Heimes date: Thu Sep 06 18:03:32 2012 +0200 summary: Issue #15591: run ctypes' configure in quiet mode when setup.py runs silently files: setup.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1788,6 +1788,8 @@ mkpath(ffi_builddir) config_args = [arg for arg in sysconfig.get_config_var("CONFIG_ARGS").split() if (('--host=' in arg) or ('--build=' in arg))] + if not self.verbose: + config_args.append("-q") # Pass empty CFLAGS because we'll just append the resulting # CFLAGS to Python's; -g or -O2 is to be avoided. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 18:06:58 2012 From: python-checkins at python.org (christian.heimes) Date: Thu, 6 Sep 2012 18:06:58 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1NTkx?= =?utf-8?q?=3A_run_ctypes=27_configure_in_quiet_mode_when_setup=2Epy_runs_?= =?utf-8?q?silently?= Message-ID: <3XCRVp62tLzQZg@mail.python.org> http://hg.python.org/cpython/rev/962e8b2a39f3 changeset: 78863:962e8b2a39f3 branch: 2.7 parent: 78855:5a2ef447b80d user: Christian Heimes date: Thu Sep 06 18:02:49 2012 +0200 summary: Issue #15591: run ctypes' configure in quiet mode when setup.py runs silently files: setup.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1872,6 +1872,8 @@ from distutils.dir_util import mkpath mkpath(ffi_builddir) config_args = [] + if not self.verbose: + config_args.append("-q") # Pass empty CFLAGS because we'll just append the resulting # CFLAGS to Python's; -g or -O2 is to be avoided. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Sep 6 19:03:04 2012 From: python-checkins at python.org (ross.lagerwall) Date: Thu, 6 Sep 2012 19:03:04 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_a_typo_in_the_curses_d?= =?utf-8?q?ocs?= Message-ID: <3XCSlX2MSJzQ9k@mail.python.org> http://hg.python.org/cpython/rev/99a436de7029 changeset: 78864:99a436de7029 parent: 78862:e5569b03a287 user: Ross Lagerwall date: Thu Sep 06 18:58:43 2012 +0200 summary: Fix a typo in the curses docs files: Doc/library/curses.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -837,7 +837,7 @@ .. attribute:: window.encoding Encoding used to encode method arguments (Unicode strings and characters). - The encoding attribute is inherited from by parent window when a subwindow + The encoding attribute is inherited from the parent window when a subwindow is created, for example with :meth:`window.subwin`. By default, the locale encoding is used (see :func:`locale.getpreferredencoding`). -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 01:19:05 2012 From: python-checkins at python.org (christian.heimes) Date: Fri, 7 Sep 2012 01:19:05 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1NTkx?= =?utf-8?q?_and_Issue_=2311715=3A_silence_output_of_setup=2Epy_when_make_i?= =?utf-8?q?s_run_with?= Message-ID: <3XCd5P6BZmzQYn@mail.python.org> http://hg.python.org/cpython/rev/b9261dd34289 changeset: 78865:b9261dd34289 branch: 3.2 parent: 78861:048e13546a7c user: Christian Heimes date: Fri Sep 07 00:55:33 2012 +0200 summary: Issue #15591 and Issue #11715: silence output of setup.py when make is run with -s option. files: Makefile.pre.in | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -198,6 +198,14 @@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py +# Find the silent flag in MAKEFLAGS. The flags are sorted and normalized +# by GNU make. The 's' flag is always in the first word. +ifneq (,$(findstring s,$(word 1,$(MAKEFLAGS)))) + QUIET=-q +else + QUIET= +endif + # === Definitions added by makesetup === @@ -438,14 +446,8 @@ # Build the shared modules sharedmods: $(BUILDPYTHON) - if which getopt >/dev/null; then \ - mflags=`getopt s $$MAKEFLAGS 2>/dev/null | sed 's/ --.*/ /'`; \ - else \ - mflags=" $$MAKEFLAGS "; \ - fi; \ - case $$mflags in "* -s *") quiet=-q; esac; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - ./$(BUILDPYTHON) -E $(srcdir)/setup.py $$quiet build + ./$(BUILDPYTHON) -E $(srcdir)/setup.py $(QUIET) build # Build static library # avoid long command lines, same as LIBRARY_OBJS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 01:19:07 2012 From: python-checkins at python.org (christian.heimes) Date: Fri, 7 Sep 2012 01:19:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315591_and_Issue_=2311715=3A_silence_output_of_s?= =?utf-8?q?etup=2Epy_when_make_is_run_with?= Message-ID: <3XCd5R2vdHzQbL@mail.python.org> http://hg.python.org/cpython/rev/fcc629208842 changeset: 78866:fcc629208842 parent: 78862:e5569b03a287 parent: 78865:b9261dd34289 user: Christian Heimes date: Fri Sep 07 00:56:56 2012 +0200 summary: Issue #15591 and Issue #11715: silence output of setup.py when make is run with -s option. files: Makefile.pre.in | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -202,6 +202,14 @@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py +# Find the silent flag in MAKEFLAGS. The flags are sorted and normalized +# by GNU make. The 's' flag is always in the first word. +ifneq (,$(findstring s,$(word 1,$(MAKEFLAGS)))) + QUIET=-q +else + QUIET= +endif + # === Definitions added by makesetup === @@ -475,14 +483,8 @@ # Build the shared modules sharedmods: $(BUILDPYTHON) $(SYSCONFIGDATA) - if which getopt >/dev/null; then \ - mflags=`getopt s $$MAKEFLAGS 2>/dev/null | sed 's/ --.*/ /'`; \ - else \ - mflags=" $$MAKEFLAGS "; \ - fi; \ - case $$mflags in "* -s *") quiet=-q; esac; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $(QUIET) build # Build static library # avoid long command lines, same as LIBRARY_OBJS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 01:19:08 2012 From: python-checkins at python.org (christian.heimes) Date: Fri, 7 Sep 2012 01:19:08 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1NTkx?= =?utf-8?q?_and_Issue_=2311715=3A_silence_output_of_setup=2Epy_when_make_i?= =?utf-8?q?s_run_with?= Message-ID: <3XCd5S5k7yzQYn@mail.python.org> http://hg.python.org/cpython/rev/2587aeb616b6 changeset: 78867:2587aeb616b6 branch: 2.7 parent: 78863:962e8b2a39f3 user: Christian Heimes date: Fri Sep 07 00:58:26 2012 +0200 summary: Issue #15591 and Issue #11715: silence output of setup.py when make is run with -s option. files: Makefile.pre.in | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -189,6 +189,14 @@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py +# Find the silent flag in MAKEFLAGS. The flags are sorted and normalized +# by GNU make. The 's' flag is always in the first word. +ifneq (,$(findstring s,$(word 1,$(MAKEFLAGS)))) + QUIET=-q +else + QUIET= +endif + # === Definitions added by makesetup === @@ -409,14 +417,8 @@ # Build the shared modules sharedmods: $(BUILDPYTHON) - if which getopt >/dev/null 2>&1; then \ - mflags=`getopt s $$MAKEFLAGS 2>/dev/null | sed 's/ --.*/ /'`; \ - else \ - mflags=" $$MAKEFLAGS "; \ - fi; \ - case $$mflags in "* -s *") quiet=-q; esac; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - ./$(BUILDPYTHON) -E $(srcdir)/setup.py $$quiet build + ./$(BUILDPYTHON) -E $(srcdir)/setup.py $(QUIET) build # Build static library # avoid long command lines, same as LIBRARY_OBJS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 01:19:10 2012 From: python-checkins at python.org (christian.heimes) Date: Fri, 7 Sep 2012 01:19:10 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315591_and_Issue_=2311715=3A_silence_output_of_s?= =?utf-8?q?etup=2Epy_when_make_is_run_with?= Message-ID: <3XCd5V1t6qzQcV@mail.python.org> http://hg.python.org/cpython/rev/4807ed8a627e changeset: 78868:4807ed8a627e parent: 78864:99a436de7029 parent: 78866:fcc629208842 user: Christian Heimes date: Fri Sep 07 01:07:12 2012 +0200 summary: Issue #15591 and Issue #11715: silence output of setup.py when make is run with -s option. files: Makefile.pre.in | 16 +++++++++------- 1 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -202,6 +202,14 @@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py +# Find the silent flag in MAKEFLAGS. The flags are sorted and normalized +# by GNU make. The 's' flag is always in the first word. +ifneq (,$(findstring s,$(word 1,$(MAKEFLAGS)))) + QUIET=-q +else + QUIET= +endif + # === Definitions added by makesetup === @@ -475,14 +483,8 @@ # Build the shared modules sharedmods: $(BUILDPYTHON) $(SYSCONFIGDATA) - if which getopt >/dev/null; then \ - mflags=`getopt s $$MAKEFLAGS 2>/dev/null | sed 's/ --.*/ /'`; \ - else \ - mflags=" $$MAKEFLAGS "; \ - fi; \ - case $$mflags in "* -s *") quiet=-q; esac; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $(QUIET) build # Build static library # avoid long command lines, same as LIBRARY_OBJS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 02:27:22 2012 From: python-checkins at python.org (christian.heimes) Date: Fri, 7 Sep 2012 02:27:22 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fix_for_fcc629?= =?utf-8?q?208842?= Message-ID: <3XCfcB1ZLFzM2t@mail.python.org> http://hg.python.org/cpython/rev/abb858a0740f changeset: 78869:abb858a0740f branch: 3.2 parent: 78865:b9261dd34289 user: Christian Heimes date: Fri Sep 07 02:24:58 2012 +0200 summary: Fix for fcc629208842 BSD's make doesn't support some of the features. files: Makefile.pre.in | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -198,14 +198,6 @@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py -# Find the silent flag in MAKEFLAGS. The flags are sorted and normalized -# by GNU make. The 's' flag is always in the first word. -ifneq (,$(findstring s,$(word 1,$(MAKEFLAGS)))) - QUIET=-q -else - QUIET= -endif - # === Definitions added by makesetup === @@ -445,9 +437,15 @@ # Build the shared modules +# MAKEFLAGS are sorted and normalized. Under GNU make the 's' for +# -s, --silent or --quiet is always the first char. sharedmods: $(BUILDPYTHON) + @case "$$MAKEFLAGS" in \ + s*) quiet="-q";; \ + *) quiet="";; \ + esac; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - ./$(BUILDPYTHON) -E $(srcdir)/setup.py $(QUIET) build + ./$(BUILDPYTHON) -E $(srcdir)/setup.py $$quiet build # Build static library # avoid long command lines, same as LIBRARY_OBJS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 02:27:23 2012 From: python-checkins at python.org (christian.heimes) Date: Fri, 7 Sep 2012 02:27:23 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Fix_for_fcc629208842?= Message-ID: <3XCfcC6x31zQJK@mail.python.org> http://hg.python.org/cpython/rev/ffcb7f5f2e48 changeset: 78870:ffcb7f5f2e48 parent: 78868:4807ed8a627e parent: 78869:abb858a0740f user: Christian Heimes date: Fri Sep 07 02:26:26 2012 +0200 summary: Fix for fcc629208842 BSD's make doesn't support some of the features. files: Makefile.pre.in | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -202,14 +202,6 @@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py -# Find the silent flag in MAKEFLAGS. The flags are sorted and normalized -# by GNU make. The 's' flag is always in the first word. -ifneq (,$(findstring s,$(word 1,$(MAKEFLAGS)))) - QUIET=-q -else - QUIET= -endif - # === Definitions added by makesetup === @@ -482,9 +474,15 @@ $(RUNSHARED) $(PYTHON_FOR_BUILD) -S -m sysconfig --generate-posix-vars # Build the shared modules +# MAKEFLAGS are sorted and normalized. Under GNU make the 's' for +# -s, --silent or --quiet is always the first char. sharedmods: $(BUILDPYTHON) $(SYSCONFIGDATA) + @case "$$MAKEFLAGS" in \ + s*) quiet="-q";; \ + *) quiet="";; \ + esac; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $(QUIET) build + $(PYTHON_FOR_BUILD) $(srcdir)/setup.py $$quiet build # Build static library # avoid long command lines, same as LIBRARY_OBJS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 02:27:25 2012 From: python-checkins at python.org (christian.heimes) Date: Fri, 7 Sep 2012 02:27:25 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1NTkx?= =?utf-8?q?_and_Issue_=2311715=3A_silence_output_of_setup=2Epy_when_make_i?= =?utf-8?q?s_run_with?= Message-ID: <3XCfcF2gx1zQLL@mail.python.org> http://hg.python.org/cpython/rev/8cd6acffbcb9 changeset: 78871:8cd6acffbcb9 branch: 2.7 parent: 78867:2587aeb616b6 user: Christian Heimes date: Fri Sep 07 00:55:33 2012 +0200 summary: Issue #15591 and Issue #11715: silence output of setup.py when make is run with -s option. files: -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Sep 7 06:05:24 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 07 Sep 2012 06:05:24 +0200 Subject: [Python-checkins] Daily reference leaks (ffcb7f5f2e48): sum=0 Message-ID: results for ffcb7f5f2e48 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogYqyJNz', '-x'] From python-checkins at python.org Fri Sep 7 08:38:27 2012 From: python-checkins at python.org (ross.lagerwall) Date: Fri, 7 Sep 2012 08:38:27 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315876=3A_Fix_a_re?= =?utf-8?q?fleak_in_the_curses_module?= Message-ID: <3XCprM0mppzQDt@mail.python.org> http://hg.python.org/cpython/rev/c82e3a6553fc changeset: 78872:c82e3a6553fc parent: 78870:ffcb7f5f2e48 user: Ross Lagerwall date: Fri Sep 07 08:34:23 2012 +0200 summary: Issue #15876: Fix a refleak in the curses module The refleak occurred when assigning to window.encoding. files: Misc/NEWS | 2 ++ Modules/_cursesmodule.c | 1 + 2 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -26,6 +26,8 @@ Library ------- +- Issue #15876: Fix a refleak in the curses module: window.encoding. + - Issue #15841: The readable(), writable() and seekable() methods of BytesIO and StringIO objects now raise ValueError when the object has been closed. Patch by Alessandro Moura. diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1938,6 +1938,7 @@ if (ascii == NULL) return -1; encoding = strdup(PyBytes_AS_STRING(ascii)); + Py_DECREF(ascii); if (encoding == NULL) { PyErr_NoMemory(); return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 14:33:18 2012 From: python-checkins at python.org (christian.heimes) Date: Fri, 7 Sep 2012 14:33:18 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Added_me_and_Brett_as_con?= =?utf-8?q?tacts_for_coverity_scan?= Message-ID: <3XCyjp4z6xzQKj@mail.python.org> http://hg.python.org/devguide/rev/8a37fda37d44 changeset: 543:8a37fda37d44 user: Christian Heimes date: Fri Sep 07 14:33:07 2012 +0200 summary: Added me and Brett as contacts for coverity scan files: experts.rst | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/experts.rst b/experts.rst --- a/experts.rst +++ b/experts.rst @@ -301,6 +301,7 @@ buildbots pitrou bytecode pitrou, georg.brandl context managers ncoghlan +coverity scan christian.heimes, brett.cannon data formats mark.dickinson, georg.brandl database lemburg devguide ncoghlan, eric.araujo, ezio.melotti -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Fri Sep 7 23:56:06 2012 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 7 Sep 2012 23:56:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1MzQw?= =?utf-8?q?=3A_Fix_importing_the_random_module_when_/dev/urandom_cannot_be?= Message-ID: <3XDCCB2tkdzQ0h@mail.python.org> http://hg.python.org/cpython/rev/2e8b01583839 changeset: 78873:2e8b01583839 branch: 3.2 parent: 78869:abb858a0740f user: Antoine Pitrou date: Fri Sep 07 23:49:07 2012 +0200 summary: Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. files: Misc/NEWS | 3 +++ Python/random.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -120,6 +120,9 @@ Library ------- +- Issue #15340: Fix importing the random module when /dev/urandom cannot + be opened. This was a regression caused by the hash randomization patch. + - Issue #15841: The readable(), writable() and seekable() methods of BytesIO and StringIO objects now raise ValueError when the object has been closed. Patch by Alessandro Moura. diff --git a/Python/random.c b/Python/random.c --- a/Python/random.c +++ b/Python/random.c @@ -165,7 +165,8 @@ Py_END_ALLOW_THREADS if (fd < 0) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/dev/urandom"); + PyErr_SetString(PyExc_NotImplementedError, + "/dev/urandom (or equivalent) not found"); return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 23:56:08 2012 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 7 Sep 2012 23:56:08 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315340=3A_Fix_importing_the_random_module_when_/?= =?utf-8?q?dev/urandom_cannot_be?= Message-ID: <3XDCCD0q7rzQ6q@mail.python.org> http://hg.python.org/cpython/rev/a53fc9982e2a changeset: 78874:a53fc9982e2a parent: 78872:c82e3a6553fc parent: 78873:2e8b01583839 user: Antoine Pitrou date: Fri Sep 07 23:51:22 2012 +0200 summary: Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. files: Misc/NEWS | 3 +++ Python/random.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -88,6 +88,9 @@ Library ------- +- Issue #15340: Fix importing the random module when /dev/urandom cannot + be opened. This was a regression caused by the hash randomization patch. + - Issue #15828: Restore support for C extensions in imp.load_module() - Issue #10650: Deprecate the watchexp parameter of the Decimal.quantize() diff --git a/Python/random.c b/Python/random.c --- a/Python/random.c +++ b/Python/random.c @@ -165,7 +165,8 @@ Py_END_ALLOW_THREADS if (fd < 0) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/dev/urandom"); + PyErr_SetString(PyExc_NotImplementedError, + "/dev/urandom (or equivalent) not found"); return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 7 23:58:48 2012 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 7 Sep 2012 23:58:48 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1MzQw?= =?utf-8?q?=3A_Fix_importing_the_random_module_when_/dev/urandom_cannot_be?= Message-ID: <3XDCGJ1Y2gzQ90@mail.python.org> http://hg.python.org/cpython/rev/edbf37ace03c changeset: 78875:edbf37ace03c branch: 2.7 parent: 78871:8cd6acffbcb9 user: Antoine Pitrou date: Fri Sep 07 23:49:07 2012 +0200 summary: Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. files: Misc/NEWS | 3 +++ Python/random.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -103,6 +103,9 @@ Library ------- +- Issue #15340: Fix importing the random module when /dev/urandom cannot + be opened. This was a regression caused by the hash randomization patch. + - Issue #15841: The readable(), writable() and seekable() methods of io.BytesIO and io.StringIO objects now raise ValueError when the object has been closed. Patch by Alessandro Moura. diff --git a/Python/random.c b/Python/random.c --- a/Python/random.c +++ b/Python/random.c @@ -165,7 +165,8 @@ Py_END_ALLOW_THREADS if (fd < 0) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/dev/urandom"); + PyErr_SetString(PyExc_NotImplementedError, + "/dev/urandom (or equivalent) not found"); return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 05:53:50 2012 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Sep 2012 05:53:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Mention_Petri=27s_git_mir?= =?utf-8?q?ror=2C_since_this_question_has_come_up_a_couple_of_times?= Message-ID: <3XDM7y0LVFzQ4s@mail.python.org> http://hg.python.org/devguide/rev/a19e721916f5 changeset: 544:a19e721916f5 user: Nick Coghlan date: Sat Sep 08 13:53:41 2012 +1000 summary: Mention Petri's git mirror, since this question has come up a couple of times now and using Petri's mirror is the simplest answer files: faq.rst | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/faq.rst b/faq.rst --- a/faq.rst +++ b/faq.rst @@ -140,6 +140,30 @@ .. _Hg Init\: a Mercurial tutorial: http://hginit.com/ +I already know how to use Git, can I use that instead? +------------------------------------------------------ + +While the main workflow for core developers requires Mercurial, if +you just want to generate patches with ``git diff`` and post them to the +`issue tracker`_, Petri Lehtinen maintains a `git mirror`_ of the main +`CPython repository`_. To create a local clone based on this mirror rather +than the main repository:: + + git clone git://github.com/akheron/cpython + +The mirror's master branch tracks the main repository's default branch, +while the maintenance branch names (``2.7``, ``3.2``, etc) are mapped +directly. + +.. _git mirror: http://github.com/akheron/cpython +.. _CPython repository: http://hg.python.org/cpython + +Please only use this approach if you're already an experienced Git user and +don't require assistance with the specifics of version control commands. All +other parts of this developer's guide assume the use of Mercurial for local +version control. + + What do I need to use Mercurial? ------------------------------------------------------------------------------- -- Repository URL: http://hg.python.org/devguide From solipsis at pitrou.net Sat Sep 8 06:04:41 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 08 Sep 2012 06:04:41 +0200 Subject: [Python-checkins] Daily reference leaks (a53fc9982e2a): sum=0 Message-ID: results for a53fc9982e2a on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogrr1UG7', '-x'] From python-checkins at python.org Sat Sep 8 11:26:34 2012 From: python-checkins at python.org (stefan.krah) Date: Sat, 8 Sep 2012 11:26:34 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1ODY4?= =?utf-8?q?=3A_Fix_refleak_in_bytesio=2Ec_=28Coverity_=23715365=29=2E?= Message-ID: <3XDVWt2MmWzQ8G@mail.python.org> http://hg.python.org/cpython/rev/df663603e67a changeset: 78876:df663603e67a branch: 3.2 parent: 78873:2e8b01583839 user: Stefan Krah date: Sat Sep 08 11:12:33 2012 +0200 summary: Issue #15868: Fix refleak in bytesio.c (Coverity #715365). files: Modules/_io/bytesio.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -692,8 +692,10 @@ } else { dict = PyDict_Copy(self->dict); - if (dict == NULL) + if (dict == NULL) { + Py_DECREF(initvalue); return NULL; + } } state = Py_BuildValue("(OnN)", initvalue, self->pos, dict); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 11:26:35 2012 From: python-checkins at python.org (stefan.krah) Date: Sat, 8 Sep 2012 11:26:35 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4yLg==?= Message-ID: <3XDVWv5xMGzQB3@mail.python.org> http://hg.python.org/cpython/rev/90c8fa612e5b changeset: 78877:90c8fa612e5b parent: 78874:a53fc9982e2a parent: 78876:df663603e67a user: Stefan Krah date: Sat Sep 08 11:19:27 2012 +0200 summary: Merge 3.2. files: Modules/_io/bytesio.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Modules/_io/bytesio.c b/Modules/_io/bytesio.c --- a/Modules/_io/bytesio.c +++ b/Modules/_io/bytesio.c @@ -692,8 +692,10 @@ } else { dict = PyDict_Copy(self->dict); - if (dict == NULL) + if (dict == NULL) { + Py_DECREF(initvalue); return NULL; + } } state = Py_BuildValue("(OnN)", initvalue, self->pos, dict); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 15:41:25 2012 From: python-checkins at python.org (stefan.krah) Date: Sat, 8 Sep 2012 15:41:25 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315814=3A_Update_w?= =?utf-8?q?hatsnew_to_the_current_state_of_hashing_memoryviews=2E?= Message-ID: <3XDc9x67MLzQGY@mail.python.org> http://hg.python.org/cpython/rev/ca81b9a3a015 changeset: 78878:ca81b9a3a015 user: Stefan Krah date: Sat Sep 08 15:35:01 2012 +0200 summary: Issue #15814: Update whatsnew to the current state of hashing memoryviews. files: Doc/whatsnew/3.3.rst | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -158,9 +158,8 @@ * Multi-dimensional comparisons are supported for any array type. -* All array types are hashable if the exporting object is hashable - and the view is read-only. (Contributed by Antoine Pitrou in - :issue:`13411`) +* One-dimensional memoryviews of hashable (read-only) types with formats B, + b or c are now hashable. (Contributed by Antoine Pitrou in :issue:`13411`) * Arbitrary slicing of any 1-D arrays type is supported. For example, it is now possible to reverse a memoryview in O(1) by using a negative step. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 17:54:05 2012 From: python-checkins at python.org (nick.coghlan) Date: Sat, 8 Sep 2012 17:54:05 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Update_to_latest_metadata_1?= =?utf-8?q?=2E3_draft?= Message-ID: <3XDg713tbfzQKZ@mail.python.org> http://hg.python.org/peps/rev/547555402269 changeset: 4508:547555402269 user: Nick Coghlan date: Sun Sep 09 01:53:56 2012 +1000 summary: Update to latest metadata 1.3 draft files: pep-0426.txt | 27 +++++++++++++++------------ 1 files changed, 15 insertions(+), 12 deletions(-) diff --git a/pep-0426.txt b/pep-0426.txt --- a/pep-0426.txt +++ b/pep-0426.txt @@ -31,9 +31,10 @@ Metadata Files ============== -The syntax defined in this PEP is for use with Python distribution metadata -files. This file format is a single set of RFC-822 headers parseable by -the ``rfc822`` or ``email`` modules. The field names listed in the +The syntax defined in this PEP is for use with Python distribution +metadata files. The file format is a simple UTF-8 encoded Key: value +format with no line length parsable by the ``email`` module with an +appropriate ``email.policy.Policy()``. The field names listed in the `Fields`_ section are used as the header names. There are two standard locations for these metadata files: @@ -51,8 +52,9 @@ Encoding ======== -Keys must be ASCII. Values are expected to be displayed as UTF-8, -but should otherwise be treated as opaque bytes. +Metadata 1.3 files are UTF-8, with the restriction that keys must be +ASCII. Parsers should be aware that older versions of the Metadata +specification do not specify an encoding. Fields ====== @@ -435,9 +437,10 @@ Provides-Extra (multiple use) ::::::::::::::::::::::::::::: -A string containing the name of an optional feature. Must be a valid Python -identifier. May be used to make a dependency conditional on whether the -optional feature has been requested. +A string containing the name of an optional feature. Must be printable +ASCII, not containing whitespace, comma (,), or square brackets []. +May be used to make a dependency conditional on whether the optional +feature has been requested. Example:: @@ -475,13 +478,13 @@ Extension (multiple-use) :::::::::::::::::::::::: -An ASCII string, not containing whitespace or the - character, that +An ASCII string, not containing whitespace or the / character, that indicates the presence of extended metadata. Additional tags defined by -the extension should be of the form string-Name:: +the extension should be of the form string/Name:: Extension: Chili - Chili-Type: Poblano - Chili-Heat: Mild + Chili/Type: Poblano + Chili/Heat: Mild Version Specifiers -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sat Sep 8 18:35:07 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 18:35:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1ODQ3OiBhbGxv?= =?utf-8?q?w_args_to_be_a_tuple_in_parse=5Fargs?= Message-ID: <3XDh2M2zJVzQF2@mail.python.org> http://hg.python.org/cpython/rev/5d8454fcc629 changeset: 78879:5d8454fcc629 branch: 3.2 parent: 78876:df663603e67a user: R David Murray date: Sat Sep 08 12:08:01 2012 -0400 summary: #15847: allow args to be a tuple in parse_args This fixes a regression introduced by the fix for issue #13922. Although args is not documented as being allowed to be a tuple, previously this worked and so naturally there are programs in the field that depend on it. Patch by Zbyszek J?drzejewski-Szmek. files: Lib/argparse.py | 5 ++++- Lib/test/test_argparse.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1701,9 +1701,12 @@ return args def parse_known_args(self, args=None, namespace=None): - # args default to the system args if args is None: + # args default to the system args args = _sys.argv[1:] + else: + # make sure that args are mutable + args = list(args) # default Namespace built from parser defaults if namespace is None: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4522,6 +4522,24 @@ class TestParseKnownArgs(TestCase): + def test_arguments_tuple(self): + parser = argparse.ArgumentParser() + parser.parse_args(()) + + def test_arguments_list(self): + parser = argparse.ArgumentParser() + parser.parse_args([]) + + def test_arguments_tuple_positional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x') + parser.parse_args(('x',)) + + def test_arguments_list_positional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x') + parser.parse_args(['x']) + def test_optionals(self): parser = argparse.ArgumentParser() parser.add_argument('--foo') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 18:35:09 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 18:35:09 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_merge_=2315847=3A_allow_args_to_be_a_tuple_in_parse=5Far?= =?utf-8?q?gs?= Message-ID: <3XDh2P0ntlzQFh@mail.python.org> http://hg.python.org/cpython/rev/76655483c5c8 changeset: 78880:76655483c5c8 parent: 78878:ca81b9a3a015 parent: 78879:5d8454fcc629 user: R David Murray date: Sat Sep 08 12:14:25 2012 -0400 summary: merge #15847: allow args to be a tuple in parse_args This fixes a regression introduced by the fix for issue #13922. Although args is not documented as being allowed to be a tuple, previously this worked and so naturally there are programs in the field that depend on it. Patch by Zbyszek J?drzejewski-Szmek. files: Lib/argparse.py | 5 ++++- Lib/test/test_argparse.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1709,9 +1709,12 @@ return args def parse_known_args(self, args=None, namespace=None): - # args default to the system args if args is None: + # args default to the system args args = _sys.argv[1:] + else: + # make sure that args are mutable + args = list(args) # default Namespace built from parser defaults if namespace is None: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4613,6 +4613,24 @@ class TestParseKnownArgs(TestCase): + def test_arguments_tuple(self): + parser = argparse.ArgumentParser() + parser.parse_args(()) + + def test_arguments_list(self): + parser = argparse.ArgumentParser() + parser.parse_args([]) + + def test_arguments_tuple_positional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x') + parser.parse_args(('x',)) + + def test_arguments_list_positional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x') + parser.parse_args(['x']) + def test_optionals(self): parser = argparse.ArgumentParser() parser.add_argument('--foo') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 18:35:10 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 18:35:10 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE1ODQ3OiBhbGxv?= =?utf-8?q?w_args_to_be_a_tuple_in_parse=5Fargs?= Message-ID: <3XDh2Q3lSwzQHL@mail.python.org> http://hg.python.org/cpython/rev/a2147bbf7868 changeset: 78881:a2147bbf7868 branch: 2.7 parent: 78875:edbf37ace03c user: R David Murray date: Sat Sep 08 12:15:25 2012 -0400 summary: #15847: allow args to be a tuple in parse_args This fixes a regression introduced by the fix for issue #13922. Although args is not documented as being allowed to be a tuple, previously this worked and so naturally there are programs in the field that depend on it. Patch by Zbyszek J?drzejewski-Szmek. files: Lib/argparse.py | 5 ++++- Lib/test/test_argparse.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1692,9 +1692,12 @@ return args def parse_known_args(self, args=None, namespace=None): - # args default to the system args if args is None: + # args default to the system args args = _sys.argv[1:] + else: + # make sure that args are mutable + args = list(args) # default Namespace built from parser defaults if namespace is None: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4486,6 +4486,24 @@ class TestParseKnownArgs(TestCase): + def test_arguments_tuple(self): + parser = argparse.ArgumentParser() + parser.parse_args(()) + + def test_arguments_list(self): + parser = argparse.ArgumentParser() + parser.parse_args([]) + + def test_arguments_tuple_positional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x') + parser.parse_args(('x',)) + + def test_arguments_list_positional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x') + parser.parse_args(['x']) + def test_optionals(self): parser = argparse.ArgumentParser() parser.add_argument('--foo') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 19:12:55 2012 From: python-checkins at python.org (christian.heimes) Date: Sat, 8 Sep 2012 19:12:55 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fix_for_fcc629?= =?utf-8?q?208842?= Message-ID: <3XDhsz6YMBzQJ6@mail.python.org> http://hg.python.org/cpython/rev/d19fa616b8fa changeset: 78882:d19fa616b8fa branch: 2.7 parent: 78871:8cd6acffbcb9 user: Christian Heimes date: Fri Sep 07 02:24:58 2012 +0200 summary: Fix for fcc629208842 BSD's make doesn't support some of the features. files: Makefile.pre.in | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -189,14 +189,6 @@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py -# Find the silent flag in MAKEFLAGS. The flags are sorted and normalized -# by GNU make. The 's' flag is always in the first word. -ifneq (,$(findstring s,$(word 1,$(MAKEFLAGS)))) - QUIET=-q -else - QUIET= -endif - # === Definitions added by makesetup === @@ -416,9 +408,15 @@ # Build the shared modules +# MAKEFLAGS are sorted and normalized. Under GNU make the 's' for +# -s, --silent or --quiet is always the first char. sharedmods: $(BUILDPYTHON) + @case "$$MAKEFLAGS" in \ + s*) quiet="-q";; \ + *) quiet="";; \ + esac; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - ./$(BUILDPYTHON) -E $(srcdir)/setup.py $(QUIET) build + ./$(BUILDPYTHON) -E $(srcdir)/setup.py $$quiet build # Build static library # avoid long command lines, same as LIBRARY_OBJS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 19:12:57 2012 From: python-checkins at python.org (christian.heimes) Date: Sat, 8 Sep 2012 19:12:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_Fix_for_fcc629208842?= Message-ID: <3XDht14yQ9zQLp@mail.python.org> http://hg.python.org/cpython/rev/0ee8ce24fcd0 changeset: 78883:0ee8ce24fcd0 branch: 2.7 parent: 78881:a2147bbf7868 parent: 78882:d19fa616b8fa user: Christian Heimes date: Sat Sep 08 19:12:05 2012 +0200 summary: Fix for fcc629208842 BSD's make doesn't support some of the features. files: Makefile.pre.in | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -189,14 +189,6 @@ PROFILE_TASK= $(srcdir)/Tools/pybench/pybench.py -n 2 --with-gc --with-syscheck #PROFILE_TASK= $(srcdir)/Lib/test/regrtest.py -# Find the silent flag in MAKEFLAGS. The flags are sorted and normalized -# by GNU make. The 's' flag is always in the first word. -ifneq (,$(findstring s,$(word 1,$(MAKEFLAGS)))) - QUIET=-q -else - QUIET= -endif - # === Definitions added by makesetup === @@ -416,9 +408,15 @@ # Build the shared modules +# MAKEFLAGS are sorted and normalized. Under GNU make the 's' for +# -s, --silent or --quiet is always the first char. sharedmods: $(BUILDPYTHON) + @case "$$MAKEFLAGS" in \ + s*) quiet="-q";; \ + *) quiet="";; \ + esac; \ $(RUNSHARED) CC='$(CC)' LDSHARED='$(BLDSHARED)' OPT='$(OPT)' \ - ./$(BUILDPYTHON) -E $(srcdir)/setup.py $(QUIET) build + ./$(BUILDPYTHON) -E $(srcdir)/setup.py $$quiet build # Build static library # avoid long command lines, same as LIBRARY_OBJS -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 19:42:42 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 19:42:42 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1NTEwOiBjbGFy?= =?utf-8?q?ify_textwrap=27s_handling_of_whitespace=2C_and_add_confirming_t?= =?utf-8?q?ests=2E?= Message-ID: <3XDjXL4BJ7zQ6B@mail.python.org> http://hg.python.org/cpython/rev/65e5f28801e1 changeset: 78884:65e5f28801e1 branch: 3.2 parent: 78879:5d8454fcc629 user: R David Murray date: Sat Sep 08 13:13:25 2012 -0400 summary: #15510: clarify textwrap's handling of whitespace, and add confirming tests. Patch by Chris Jerdonek. files: Doc/library/textwrap.rst | 19 +++++-- Lib/test/test_textwrap.py | 64 +++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst --- a/Doc/library/textwrap.rst +++ b/Doc/library/textwrap.rst @@ -25,6 +25,9 @@ Optional keyword arguments correspond to the instance attributes of :class:`TextWrapper`, documented below. *width* defaults to ``70``. + See the :meth:`TextWrapper.wrap` method for additional details on how + :func:`wrap` behaves. + .. function:: fill(text, width=70, **kwargs) @@ -131,15 +134,18 @@ .. attribute:: drop_whitespace - (default: ``True``) If true, whitespace that, after wrapping, happens to - end up at the beginning or end of a line is dropped (leading whitespace in - the first line is always preserved, though). + (default: ``True``) If true, whitespace at the beginning and ending of + every line (after wrapping but before indenting) is dropped. + Whitespace at the beginning of the paragraph, however, is not dropped + if non-whitespace follows it. If whitespace being dropped takes up an + entire line, the whole line is dropped. .. attribute:: initial_indent (default: ``''``) String that will be prepended to the first line of - wrapped output. Counts towards the length of the first line. + wrapped output. Counts towards the length of the first line. The empty + string is not indented. .. attribute:: subsequent_indent @@ -200,8 +206,9 @@ Wraps the single paragraph in *text* (a string) so every line is at most :attr:`width` characters long. All wrapping options are taken from - instance attributes of the :class:`TextWrapper` instance. Returns a list - of output lines, without final newlines. + instance attributes of the :class:`TextWrapper` instance. Returns a list + of output lines, without final newlines. If the wrapped output has no + content, the returned list is empty. .. method:: fill(text) diff --git a/Lib/test/test_textwrap.py b/Lib/test/test_textwrap.py --- a/Lib/test/test_textwrap.py +++ b/Lib/test/test_textwrap.py @@ -22,7 +22,7 @@ result = [] for i in range(len(textin)): result.append(" %d: %r" % (i, textin[i])) - result = '\n'.join(result) + result = "\n".join(result) if result else " no lines" elif isinstance(textin, str): result = " %s\n" % repr(textin) return result @@ -66,6 +66,15 @@ "I'm glad to hear it!"]) self.check_wrap(text, 80, [text]) + def test_empty_string(self): + # Check that wrapping the empty string returns an empty list. + self.check_wrap("", 6, []) + self.check_wrap("", 6, [], drop_whitespace=False) + + def test_empty_string_with_initial_indent(self): + # Check that the empty string is not indented. + self.check_wrap("", 6, [], initial_indent="++") + self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False) def test_whitespace(self): # Whitespace munging and end-of-sentence detection @@ -323,7 +332,32 @@ ["blah", " ", "(ding", " ", "dong),", " ", "wubba"]) - def test_initial_whitespace(self): + def test_drop_whitespace_false(self): + # Check that drop_whitespace=False preserves whitespace. + # SF patch #1581073 + text = " This is a sentence with much whitespace." + self.check_wrap(text, 10, + [" This is a", " ", "sentence ", + "with ", "much white", "space."], + drop_whitespace=False) + + def test_drop_whitespace_false_whitespace_only(self): + # Check that drop_whitespace=False preserves a whitespace-only string. + self.check_wrap(" ", 6, [" "], drop_whitespace=False) + + def test_drop_whitespace_false_whitespace_only_with_indent(self): + # Check that a whitespace-only string gets indented (when + # drop_whitespace is False). + self.check_wrap(" ", 6, [" "], drop_whitespace=False, + initial_indent=" ") + + def test_drop_whitespace_whitespace_only(self): + # Check drop_whitespace on a whitespace-only string. + self.check_wrap(" ", 6, []) + + def test_drop_whitespace_leading_whitespace(self): + # Check that drop_whitespace does not drop leading whitespace (if + # followed by non-whitespace). # SF bug #622849 reported inconsistent handling of leading # whitespace; let's test that a bit, shall we? text = " This is a sentence with leading whitespace." @@ -332,13 +366,27 @@ self.check_wrap(text, 30, [" This is a sentence with", "leading whitespace."]) - def test_no_drop_whitespace(self): - # SF patch #1581073 - text = " This is a sentence with much whitespace." - self.check_wrap(text, 10, - [" This is a", " ", "sentence ", - "with ", "much white", "space."], + def test_drop_whitespace_whitespace_line(self): + # Check that drop_whitespace skips the whole line if a non-leading + # line consists only of whitespace. + text = "abcd efgh" + # Include the result for drop_whitespace=False for comparison. + self.check_wrap(text, 6, ["abcd", " ", "efgh"], drop_whitespace=False) + self.check_wrap(text, 6, ["abcd", "efgh"]) + + def test_drop_whitespace_whitespace_only_with_indent(self): + # Check that initial_indent is not applied to a whitespace-only + # string. This checks a special case of the fact that dropping + # whitespace occurs before indenting. + self.check_wrap(" ", 6, [], initial_indent="++") + + def test_drop_whitespace_whitespace_indent(self): + # Check that drop_whitespace does not drop whitespace indents. + # This checks a special case of the fact that dropping whitespace + # occurs before indenting. + self.check_wrap("abcd efgh", 6, [" abcd", " efgh"], + initial_indent=" ", subsequent_indent=" ") def test_split(self): # Ensure that the standard _split() method works as advertised -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 19:42:44 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 19:42:44 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2315510=3A_clarify_textwrap=27s_handling_of_white?= =?utf-8?q?space=2C_and_add_confirming?= Message-ID: <3XDjXN3CgqzQKZ@mail.python.org> http://hg.python.org/cpython/rev/0e9ad455355b changeset: 78885:0e9ad455355b parent: 78880:76655483c5c8 parent: 78884:65e5f28801e1 user: R David Murray date: Sat Sep 08 13:14:58 2012 -0400 summary: Merge #15510: clarify textwrap's handling of whitespace, and add confirming tests. Patch by Chris Jerdonek. files: Doc/library/textwrap.rst | 19 +++++-- Lib/test/test_textwrap.py | 64 +++++++++++++++++++++++--- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst --- a/Doc/library/textwrap.rst +++ b/Doc/library/textwrap.rst @@ -25,6 +25,9 @@ Optional keyword arguments correspond to the instance attributes of :class:`TextWrapper`, documented below. *width* defaults to ``70``. + See the :meth:`TextWrapper.wrap` method for additional details on how + :func:`wrap` behaves. + .. function:: fill(text, width=70, **kwargs) @@ -167,15 +170,18 @@ .. attribute:: drop_whitespace - (default: ``True``) If true, whitespace that, after wrapping, happens to - end up at the beginning or end of a line is dropped (leading whitespace in - the first line is always preserved, though). + (default: ``True``) If true, whitespace at the beginning and ending of + every line (after wrapping but before indenting) is dropped. + Whitespace at the beginning of the paragraph, however, is not dropped + if non-whitespace follows it. If whitespace being dropped takes up an + entire line, the whole line is dropped. .. attribute:: initial_indent (default: ``''``) String that will be prepended to the first line of - wrapped output. Counts towards the length of the first line. + wrapped output. Counts towards the length of the first line. The empty + string is not indented. .. attribute:: subsequent_indent @@ -236,8 +242,9 @@ Wraps the single paragraph in *text* (a string) so every line is at most :attr:`width` characters long. All wrapping options are taken from - instance attributes of the :class:`TextWrapper` instance. Returns a list - of output lines, without final newlines. + instance attributes of the :class:`TextWrapper` instance. Returns a list + of output lines, without final newlines. If the wrapped output has no + content, the returned list is empty. .. method:: fill(text) diff --git a/Lib/test/test_textwrap.py b/Lib/test/test_textwrap.py --- a/Lib/test/test_textwrap.py +++ b/Lib/test/test_textwrap.py @@ -22,7 +22,7 @@ result = [] for i in range(len(textin)): result.append(" %d: %r" % (i, textin[i])) - result = '\n'.join(result) + result = "\n".join(result) if result else " no lines" elif isinstance(textin, str): result = " %s\n" % repr(textin) return result @@ -66,6 +66,15 @@ "I'm glad to hear it!"]) self.check_wrap(text, 80, [text]) + def test_empty_string(self): + # Check that wrapping the empty string returns an empty list. + self.check_wrap("", 6, []) + self.check_wrap("", 6, [], drop_whitespace=False) + + def test_empty_string_with_initial_indent(self): + # Check that the empty string is not indented. + self.check_wrap("", 6, [], initial_indent="++") + self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False) def test_whitespace(self): # Whitespace munging and end-of-sentence detection @@ -331,7 +340,32 @@ ["blah", " ", "(ding", " ", "dong),", " ", "wubba"]) - def test_initial_whitespace(self): + def test_drop_whitespace_false(self): + # Check that drop_whitespace=False preserves whitespace. + # SF patch #1581073 + text = " This is a sentence with much whitespace." + self.check_wrap(text, 10, + [" This is a", " ", "sentence ", + "with ", "much white", "space."], + drop_whitespace=False) + + def test_drop_whitespace_false_whitespace_only(self): + # Check that drop_whitespace=False preserves a whitespace-only string. + self.check_wrap(" ", 6, [" "], drop_whitespace=False) + + def test_drop_whitespace_false_whitespace_only_with_indent(self): + # Check that a whitespace-only string gets indented (when + # drop_whitespace is False). + self.check_wrap(" ", 6, [" "], drop_whitespace=False, + initial_indent=" ") + + def test_drop_whitespace_whitespace_only(self): + # Check drop_whitespace on a whitespace-only string. + self.check_wrap(" ", 6, []) + + def test_drop_whitespace_leading_whitespace(self): + # Check that drop_whitespace does not drop leading whitespace (if + # followed by non-whitespace). # SF bug #622849 reported inconsistent handling of leading # whitespace; let's test that a bit, shall we? text = " This is a sentence with leading whitespace." @@ -340,13 +374,27 @@ self.check_wrap(text, 30, [" This is a sentence with", "leading whitespace."]) - def test_no_drop_whitespace(self): - # SF patch #1581073 - text = " This is a sentence with much whitespace." - self.check_wrap(text, 10, - [" This is a", " ", "sentence ", - "with ", "much white", "space."], + def test_drop_whitespace_whitespace_line(self): + # Check that drop_whitespace skips the whole line if a non-leading + # line consists only of whitespace. + text = "abcd efgh" + # Include the result for drop_whitespace=False for comparison. + self.check_wrap(text, 6, ["abcd", " ", "efgh"], drop_whitespace=False) + self.check_wrap(text, 6, ["abcd", "efgh"]) + + def test_drop_whitespace_whitespace_only_with_indent(self): + # Check that initial_indent is not applied to a whitespace-only + # string. This checks a special case of the fact that dropping + # whitespace occurs before indenting. + self.check_wrap(" ", 6, [], initial_indent="++") + + def test_drop_whitespace_whitespace_indent(self): + # Check that drop_whitespace does not drop whitespace indents. + # This checks a special case of the fact that dropping whitespace + # occurs before indenting. + self.check_wrap("abcd efgh", 6, [" abcd", " efgh"], + initial_indent=" ", subsequent_indent=" ") def test_split(self): # Ensure that the standard _split() method works as advertised -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 19:42:46 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 19:42:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE1NTEwOiBjbGFy?= =?utf-8?q?ify_textwrap=27s_handling_of_whitespace=2C_and_add_confirming_t?= =?utf-8?q?ests=2E?= Message-ID: <3XDjXQ1KRczQKZ@mail.python.org> http://hg.python.org/cpython/rev/fca48971ac35 changeset: 78886:fca48971ac35 branch: 2.7 parent: 78883:0ee8ce24fcd0 user: R David Murray date: Sat Sep 08 13:42:01 2012 -0400 summary: #15510: clarify textwrap's handling of whitespace, and add confirming tests. Patch by Chris Jerdonek. files: Doc/library/textwrap.rst | 19 +++++-- Lib/test/test_textwrap.py | 62 +++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 13 deletions(-) diff --git a/Doc/library/textwrap.rst b/Doc/library/textwrap.rst --- a/Doc/library/textwrap.rst +++ b/Doc/library/textwrap.rst @@ -26,6 +26,9 @@ Optional keyword arguments correspond to the instance attributes of :class:`TextWrapper`, documented below. *width* defaults to ``70``. + See the :meth:`TextWrapper.wrap` method for additional details on how + :func:`wrap` behaves. + .. function:: fill(text[, width[, ...]]) @@ -134,9 +137,11 @@ .. attribute:: drop_whitespace - (default: ``True``) If true, whitespace that, after wrapping, happens to - end up at the beginning or end of a line is dropped (leading whitespace in - the first line is always preserved, though). + (default: ``True``) If true, whitespace at the beginning and ending of + every line (after wrapping but before indenting) is dropped. + Whitespace at the beginning of the paragraph, however, is not dropped + if non-whitespace follows it. If whitespace being dropped takes up an + entire line, the whole line is dropped. .. versionadded:: 2.6 Whitespace was always dropped in earlier versions. @@ -145,7 +150,8 @@ .. attribute:: initial_indent (default: ``''``) String that will be prepended to the first line of - wrapped output. Counts towards the length of the first line. + wrapped output. Counts towards the length of the first line. The empty + string is not indented. .. attribute:: subsequent_indent @@ -208,8 +214,9 @@ Wraps the single paragraph in *text* (a string) so every line is at most :attr:`width` characters long. All wrapping options are taken from - instance attributes of the :class:`TextWrapper` instance. Returns a list - of output lines, without final newlines. + instance attributes of the :class:`TextWrapper` instance. Returns a list + of output lines, without final newlines. If the wrapped output has no + content, the returned list is empty. .. method:: fill(text) diff --git a/Lib/test/test_textwrap.py b/Lib/test/test_textwrap.py --- a/Lib/test/test_textwrap.py +++ b/Lib/test/test_textwrap.py @@ -66,6 +66,15 @@ "I'm glad to hear it!"]) self.check_wrap(text, 80, [text]) + def test_empty_string(self): + # Check that wrapping the empty string returns an empty list. + self.check_wrap("", 6, []) + self.check_wrap("", 6, [], drop_whitespace=False) + + def test_empty_string_with_initial_indent(self): + # Check that the empty string is not indented. + self.check_wrap("", 6, [], initial_indent="++") + self.check_wrap("", 6, [], initial_indent="++", drop_whitespace=False) def test_whitespace(self): # Whitespace munging and end-of-sentence detection @@ -323,7 +332,32 @@ ["blah", " ", "(ding", " ", "dong),", " ", "wubba"]) - def test_initial_whitespace(self): + def test_drop_whitespace_false(self): + # Check that drop_whitespace=False preserves whitespace. + # SF patch #1581073 + text = " This is a sentence with much whitespace." + self.check_wrap(text, 10, + [" This is a", " ", "sentence ", + "with ", "much white", "space."], + drop_whitespace=False) + + def test_drop_whitespace_false_whitespace_only(self): + # Check that drop_whitespace=False preserves a whitespace-only string. + self.check_wrap(" ", 6, [" "], drop_whitespace=False) + + def test_drop_whitespace_false_whitespace_only_with_indent(self): + # Check that a whitespace-only string gets indented (when + # drop_whitespace is False). + self.check_wrap(" ", 6, [" "], drop_whitespace=False, + initial_indent=" ") + + def test_drop_whitespace_whitespace_only(self): + # Check drop_whitespace on a whitespace-only string. + self.check_wrap(" ", 6, []) + + def test_drop_whitespace_leading_whitespace(self): + # Check that drop_whitespace does not drop leading whitespace (if + # followed by non-whitespace). # SF bug #622849 reported inconsistent handling of leading # whitespace; let's test that a bit, shall we? text = " This is a sentence with leading whitespace." @@ -332,13 +366,27 @@ self.check_wrap(text, 30, [" This is a sentence with", "leading whitespace."]) - def test_no_drop_whitespace(self): - # SF patch #1581073 - text = " This is a sentence with much whitespace." - self.check_wrap(text, 10, - [" This is a", " ", "sentence ", - "with ", "much white", "space."], + def test_drop_whitespace_whitespace_line(self): + # Check that drop_whitespace skips the whole line if a non-leading + # line consists only of whitespace. + text = "abcd efgh" + # Include the result for drop_whitespace=False for comparison. + self.check_wrap(text, 6, ["abcd", " ", "efgh"], drop_whitespace=False) + self.check_wrap(text, 6, ["abcd", "efgh"]) + + def test_drop_whitespace_whitespace_only_with_indent(self): + # Check that initial_indent is not applied to a whitespace-only + # string. This checks a special case of the fact that dropping + # whitespace occurs before indenting. + self.check_wrap(" ", 6, [], initial_indent="++") + + def test_drop_whitespace_whitespace_indent(self): + # Check that drop_whitespace does not drop whitespace indents. + # This checks a special case of the fact that dropping whitespace + # occurs before indenting. + self.check_wrap("abcd efgh", 6, [" abcd", " efgh"], + initial_indent=" ", subsequent_indent=" ") if test_support.have_unicode: def test_unicode(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 19:53:11 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 8 Sep 2012 19:53:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1ODY1OiBhZGQg?= =?utf-8?q?=22*=22_in_the_signature_to_document_keyword-only_args_in_the_d?= =?utf-8?q?ocs=2E?= Message-ID: <3XDjmR2dfrzQPg@mail.python.org> http://hg.python.org/cpython/rev/a30b3915228b changeset: 78887:a30b3915228b branch: 3.2 parent: 78879:5d8454fcc629 user: Ezio Melotti date: Sat Sep 08 20:46:01 2012 +0300 summary: #15865: add "*" in the signature to document keyword-only args in the docs. Patch by Chris Jerdonek. files: Doc/library/configparser.rst | 16 +++++++++++----- Doc/library/nntplib.rst | 6 +++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -1007,7 +1007,7 @@ .. versionadded:: 3.2 - .. method:: get(section, option, raw=False, [vars, fallback]) + .. method:: get(section, option, *, raw=False, vars=None[, fallback]) Get an *option* value for the named *section*. If *vars* is provided, it must be a dictionary. The *option* is looked up in *vars* (if provided), @@ -1025,21 +1025,21 @@ (especially when using the mapping protocol). - .. method:: getint(section, option, raw=False, [vars, fallback]) + .. method:: getint(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to an integer. See :meth:`get` for explanation of *raw*, *vars* and *fallback*. - .. method:: getfloat(section, option, raw=False, [vars, fallback]) + .. method:: getfloat(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to a floating point number. See :meth:`get` for explanation of *raw*, *vars* and *fallback*. - .. method:: getboolean(section, option, raw=False, [vars, fallback]) + .. method:: getboolean(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to a Boolean value. Note that the accepted values for the option are @@ -1149,7 +1149,13 @@ RawConfigParser Objects ----------------------- -.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=configaparser.DEFAULTSECT, interpolation=None) +.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, \ + allow_no_value=False, *, delimiters=('=', ':'), \ + comment_prefixes=('#', ';'), \ + inline_comment_prefixes=None, strict=True, \ + empty_lines_in_values=True, \ + default_section=configparser.DEFAULTSECT[, \ + interpolation]) Legacy variant of the :class:`ConfigParser` with interpolation disabled by default and unsafe ``add_section`` and ``set`` methods. diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst --- a/Doc/library/nntplib.rst +++ b/Doc/library/nntplib.rst @@ -474,10 +474,10 @@ them have been superseded by newer commands in :rfc:`3977`. -.. method:: NNTP.xhdr(header, string, *, file=None) +.. method:: NNTP.xhdr(hdr, str, *, file=None) - Send an ``XHDR`` command. The *header* argument is a header keyword, e.g. - ``'subject'``. The *string* argument should have the form ``'first-last'`` + Send an ``XHDR`` command. The *hdr* argument is a header keyword, e.g. + ``'subject'``. The *str* argument should have the form ``'first-last'`` where *first* and *last* are the first and last article numbers to search. Return a pair ``(response, list)``, where *list* is a list of pairs ``(id, text)``, where *id* is an article number (as a string) and *text* is the text of -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 19:53:13 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 8 Sep 2012 19:53:13 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?b?KTogIzE1ODY1OiBtZXJnZSB3aXRoIDMuMi4=?= Message-ID: <3XDjmT1WcdzQPT@mail.python.org> http://hg.python.org/cpython/rev/694c725f241a changeset: 78888:694c725f241a parent: 78885:0e9ad455355b parent: 78887:a30b3915228b user: Ezio Melotti date: Sat Sep 08 20:49:18 2012 +0300 summary: #15865: merge with 3.2. files: Doc/library/configparser.rst | 16 +++++++++++----- Doc/library/nntplib.rst | 6 +++--- Doc/library/threading.rst | 6 ++---- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -1007,7 +1007,7 @@ .. versionadded:: 3.2 - .. method:: get(section, option, raw=False, [vars, fallback]) + .. method:: get(section, option, *, raw=False, vars=None[, fallback]) Get an *option* value for the named *section*. If *vars* is provided, it must be a dictionary. The *option* is looked up in *vars* (if provided), @@ -1025,21 +1025,21 @@ (especially when using the mapping protocol). - .. method:: getint(section, option, raw=False, [vars, fallback]) + .. method:: getint(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to an integer. See :meth:`get` for explanation of *raw*, *vars* and *fallback*. - .. method:: getfloat(section, option, raw=False, [vars, fallback]) + .. method:: getfloat(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to a floating point number. See :meth:`get` for explanation of *raw*, *vars* and *fallback*. - .. method:: getboolean(section, option, raw=False, [vars, fallback]) + .. method:: getboolean(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to a Boolean value. Note that the accepted values for the option are @@ -1149,7 +1149,13 @@ RawConfigParser Objects ----------------------- -.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=configaparser.DEFAULTSECT, interpolation=None) +.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, \ + allow_no_value=False, *, delimiters=('=', ':'), \ + comment_prefixes=('#', ';'), \ + inline_comment_prefixes=None, strict=True, \ + empty_lines_in_values=True, \ + default_section=configparser.DEFAULTSECT[, \ + interpolation]) Legacy variant of the :class:`ConfigParser` with interpolation disabled by default and unsafe ``add_section`` and ``set`` methods. diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst --- a/Doc/library/nntplib.rst +++ b/Doc/library/nntplib.rst @@ -487,10 +487,10 @@ them have been superseded by newer commands in :rfc:`3977`. -.. method:: NNTP.xhdr(header, string, *, file=None) +.. method:: NNTP.xhdr(hdr, str, *, file=None) - Send an ``XHDR`` command. The *header* argument is a header keyword, e.g. - ``'subject'``. The *string* argument should have the form ``'first-last'`` + Send an ``XHDR`` command. The *hdr* argument is a header keyword, e.g. + ``'subject'``. The *str* argument should have the form ``'first-last'`` where *first* and *last* are the first and last article numbers to search. Return a pair ``(response, list)``, where *list* is a list of pairs ``(id, text)``, where *id* is an article number (as a string) and *text* is the text of diff --git a/Doc/library/threading.rst b/Doc/library/threading.rst --- a/Doc/library/threading.rst +++ b/Doc/library/threading.rst @@ -255,8 +255,8 @@ since it is impossible to detect the termination of alien threads. -.. class:: Thread(group=None, target=None, name=None, args=(), kwargs={}, - verbose=None, *, daemon=None) +.. class:: Thread(group=None, target=None, name=None, args=(), kwargs={}, *, \ + daemon=None) This constructor should always be called with keyword arguments. Arguments are: @@ -275,8 +275,6 @@ *kwargs* is a dictionary of keyword arguments for the target invocation. Defaults to ``{}``. - *verbose* is a flag used for debugging messages. - If not ``None``, *daemon* explicitly sets whether the thread is daemonic. If ``None`` (the default), the daemonic property is inherited from the current thread. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 19:53:14 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 8 Sep 2012 19:53:14 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMik6?= =?utf-8?q?_Merge_heads=2E?= Message-ID: <3XDjmV4MLnzQQG@mail.python.org> http://hg.python.org/cpython/rev/90b6aa842d9b changeset: 78889:90b6aa842d9b branch: 3.2 parent: 78884:65e5f28801e1 parent: 78887:a30b3915228b user: Ezio Melotti date: Sat Sep 08 20:52:19 2012 +0300 summary: Merge heads. files: Doc/library/configparser.rst | 16 +++++++++++----- Doc/library/nntplib.rst | 6 +++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -1007,7 +1007,7 @@ .. versionadded:: 3.2 - .. method:: get(section, option, raw=False, [vars, fallback]) + .. method:: get(section, option, *, raw=False, vars=None[, fallback]) Get an *option* value for the named *section*. If *vars* is provided, it must be a dictionary. The *option* is looked up in *vars* (if provided), @@ -1025,21 +1025,21 @@ (especially when using the mapping protocol). - .. method:: getint(section, option, raw=False, [vars, fallback]) + .. method:: getint(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to an integer. See :meth:`get` for explanation of *raw*, *vars* and *fallback*. - .. method:: getfloat(section, option, raw=False, [vars, fallback]) + .. method:: getfloat(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to a floating point number. See :meth:`get` for explanation of *raw*, *vars* and *fallback*. - .. method:: getboolean(section, option, raw=False, [vars, fallback]) + .. method:: getboolean(section, option, *, raw=False, vars=None[, fallback]) A convenience method which coerces the *option* in the specified *section* to a Boolean value. Note that the accepted values for the option are @@ -1149,7 +1149,13 @@ RawConfigParser Objects ----------------------- -.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, allow_no_value=False, delimiters=('=', ':'), comment_prefixes=('#', ';'), inline_comment_prefixes=None, strict=True, empty_lines_in_values=True, default_section=configaparser.DEFAULTSECT, interpolation=None) +.. class:: RawConfigParser(defaults=None, dict_type=collections.OrderedDict, \ + allow_no_value=False, *, delimiters=('=', ':'), \ + comment_prefixes=('#', ';'), \ + inline_comment_prefixes=None, strict=True, \ + empty_lines_in_values=True, \ + default_section=configparser.DEFAULTSECT[, \ + interpolation]) Legacy variant of the :class:`ConfigParser` with interpolation disabled by default and unsafe ``add_section`` and ``set`` methods. diff --git a/Doc/library/nntplib.rst b/Doc/library/nntplib.rst --- a/Doc/library/nntplib.rst +++ b/Doc/library/nntplib.rst @@ -474,10 +474,10 @@ them have been superseded by newer commands in :rfc:`3977`. -.. method:: NNTP.xhdr(header, string, *, file=None) +.. method:: NNTP.xhdr(hdr, str, *, file=None) - Send an ``XHDR`` command. The *header* argument is a header keyword, e.g. - ``'subject'``. The *string* argument should have the form ``'first-last'`` + Send an ``XHDR`` command. The *hdr* argument is a header keyword, e.g. + ``'subject'``. The *str* argument should have the form ``'first-last'`` where *first* and *last* are the first and last article numbers to search. Return a pair ``(response, list)``, where *list* is a list of pairs ``(id, text)``, where *id* is an article number (as a string) and *text* is the text of -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 22:44:09 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 22:44:09 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgRXppbydzICdtZXJnZSBoZWFkcycu?= Message-ID: <3XDnYj53nNzPSW@mail.python.org> http://hg.python.org/cpython/rev/7e1b46d3e24c changeset: 78890:7e1b46d3e24c parent: 78888:694c725f241a parent: 78889:90b6aa842d9b user: R David Murray date: Sat Sep 08 16:43:17 2012 -0400 summary: Merge Ezio's 'merge heads'. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 22:48:37 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 22:48:37 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzUwODg6IGRvY3Vt?= =?utf-8?q?ent_behavior_of_optparse_defaults_with_=27append=27_action=2E?= Message-ID: <3XDnfs39C1zQM4@mail.python.org> http://hg.python.org/cpython/rev/8c60bb098eff changeset: 78891:8c60bb098eff branch: 3.2 parent: 78889:90b6aa842d9b user: R David Murray date: Sat Sep 08 16:45:35 2012 -0400 summary: #5088: document behavior of optparse defaults with 'append' action. files: Doc/library/optparse.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -1165,6 +1165,17 @@ options.tracks.append(int("4")) + The ``append`` action calls the ``append`` method on the current value of the + option. This means that any default value specified must have an ``append`` + method. It also means that if the default value is non-empty, the default + elements will be present in the parsed value for the option, with any values + from the command line appended after those default values:: + + >>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults']) + >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg']) + >>> opts.files + ['~/.mypkg/defaults', 'overrides.mypkg'] + * ``"append_const"`` [required: :attr:`~Option.const`; relevant: :attr:`~Option.dest`] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 22:48:39 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 22:48:39 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Merge_=235088=3A_document_behavior_of_optparse_defaults_?= =?utf-8?q?with_=27append=27_action=2E?= Message-ID: <3XDnfv17PbzQVV@mail.python.org> http://hg.python.org/cpython/rev/0c2bdd2c2032 changeset: 78892:0c2bdd2c2032 parent: 78890:7e1b46d3e24c parent: 78891:8c60bb098eff user: R David Murray date: Sat Sep 08 16:46:10 2012 -0400 summary: Merge #5088: document behavior of optparse defaults with 'append' action. files: Doc/library/optparse.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -1165,6 +1165,17 @@ options.tracks.append(int("4")) + The ``append`` action calls the ``append`` method on the current value of the + option. This means that any default value specified must have an ``append`` + method. It also means that if the default value is non-empty, the default + elements will be present in the parsed value for the option, with any values + from the command line appended after those default values:: + + >>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults']) + >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg']) + >>> opts.files + ['~/.mypkg/defaults', 'overrides.mypkg'] + * ``"append_const"`` [required: :attr:`~Option.const`; relevant: :attr:`~Option.dest`] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 22:48:40 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 22:48:40 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogY2xvc2VzICM1MDg4?= =?utf-8?q?=3A_document_behavior_of_optparse_defaults_with_=27append=27_ac?= =?utf-8?q?tion=2E?= Message-ID: <3XDnfw3xtDzQVX@mail.python.org> http://hg.python.org/cpython/rev/79f6d4aff39d changeset: 78893:79f6d4aff39d branch: 2.7 parent: 78886:fca48971ac35 user: R David Murray date: Sat Sep 08 16:47:24 2012 -0400 summary: closes #5088: document behavior of optparse defaults with 'append' action. files: Doc/library/optparse.rst | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -1168,6 +1168,17 @@ options.tracks.append(int("4")) + The ``append`` action calls the ``append`` method on the current value of the + option. This means that any default value specified must have an ``append`` + method. It also means that if the default value is non-empty, the default + elements will be present in the parsed value for the option, with any values + from the command line appended after those default values:: + + >>> parser.add_option("--files", action="append", default=['~/.mypkg/defaults']) + >>> opts, args = parser.parse_args(['--files', 'overrides.mypkg']) + >>> opts.files + ['~/.mypkg/defaults', 'overrides.mypkg'] + * ``"append_const"`` [required: :attr:`~Option.const`; relevant: :attr:`~Option.dest`] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 8 23:51:43 2012 From: python-checkins at python.org (r.david.murray) Date: Sat, 8 Sep 2012 23:51:43 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?devguide=3A_=2315820=3A_Improve_the_H?= =?utf-8?q?elping_with_the_Devguide_section?= Message-ID: <3XDq3g6CGvzQVv@mail.python.org> http://hg.python.org/devguide/rev/18e31605b161 changeset: 545:18e31605b161 user: R David Murray date: Sat Sep 08 17:51:33 2012 -0400 summary: #15820: Improve the Helping with the Devguide section Original idea and initial patch by Mike Hoy. Blame me for the actual result, though. files: docquality.rst | 37 ++++++++++++++++++++++++++++--------- index.rst | 5 ++--- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/docquality.rst b/docquality.rst --- a/docquality.rst +++ b/docquality.rst @@ -66,18 +66,37 @@ makes it harder to break the work up for multiple people to help with. +.. _helping-with-the-developers-guide: + Helping with the Developer's Guide ---------------------------------- -The Developer's Guide uses the same process as the main Python -documentation, except for some small differences. -The source lives in a `separate repository`_. To build and view the -documentation, install `Sphinx`_ and issue the following command: :: - - make html - -Changes to the documentation are normally published within a day on a -schedule that may be different from the main documentation. +The Developer's Guide uses the same process as the main Python documentation, +except for some small differences. The source lives in a `separate +repository`_. Bug reports and and patches should be submitted to the `python +bug tracker`_ using the ``devguide`` component. Changes to the devguide +are normally published within a day, on a schedule that may be different from +the main documentation. .. _separate repository: http://hg.python.org/devguide +.. _python bug tracker: http://bugs.python.org + +To clone the Developer's Guide: + +``hg clone http://hg.python.org/devguide`` + +Core developers should use: + +``hg clone ssh://hg at hg.python.org/devguide`` + +instead so that they can push back their edits to the server. + +To build the devguide, you must have `Sphinx`_ installed. The devguide html +can be built by running: + + make html + +in the checkout directory, which will write the files to the ``_build/html`` +directory. + .. _Sphinx: http://sphinx.pocoo.org/ diff --git a/index.rst b/index.rst --- a/index.rst +++ b/index.rst @@ -150,9 +150,8 @@ Resources --------- -* Anyone can clone this guide from http://hg.python.org/devguide/. Core - developers should use ssh://hg at hg.python.org/devguide instead, so that they - can push back their edits to the server. +* Anyone can clone the sources for this guide. See + :ref:`helping-with-the-developers-guide`. * Coding style guides * :PEP:`7` (Style Guide for C Code) * :PEP:`8` (Style Guide for Python Code) -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Sep 9 04:08:54 2012 From: python-checkins at python.org (ned.deily) Date: Sun, 9 Sep 2012 04:08:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1ODIy?= =?utf-8?q?=3A_Fix_installation_of_lib2to3_grammar_pickles_to_ensure?= Message-ID: <3XDwmQ5zMvzQ3Y@mail.python.org> http://hg.python.org/cpython/rev/2def9ef683da changeset: 78894:2def9ef683da branch: 2.7 user: Ned Deily date: Sat Sep 08 18:47:27 2012 -0700 summary: Issue #15822: Fix installation of lib2to3 grammar pickles to ensure they are created in the install locations and with the proper timestamp. (Solution suggested by MvL) files: Lib/lib2to3/pgen2/driver.py | 17 +++++++++++++++++ Makefile.pre.in | 8 +++++--- Misc/NEWS | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -138,3 +138,20 @@ if not os.path.exists(b): return True return os.path.getmtime(a) >= os.path.getmtime(b) + + +def main(*args): + """Main program, when run as a script: produce grammar pickle files. + + Calls load_grammar for each argument, a path to a grammar text file. + """ + if not args: + args = sys.argv[1:] + logging.basicConfig(level=logging.INFO, stream=sys.stdout, + format='%(message)s') + for gt in args: + load_grammar(gt, save=True, force=True) + return True + +if __name__ == "__main__": + sys.exit(int(not main())) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -887,8 +887,6 @@ lib-old \ curses pydoc_data $(MACHDEPS) libinstall: build_all $(srcdir)/Lib/$(PLATDIR) $(srcdir)/Modules/xxmodule.c - -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - ./$(BUILDPYTHON) -Wi -t -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" @for i in $(SCRIPTDIR) $(LIBDEST); \ do \ if test ! -d $(DESTDIR)$$i; then \ @@ -966,6 +964,10 @@ ./$(BUILDPYTHON) -Wi -t -O $(DESTDIR)$(LIBDEST)/compileall.py \ -d $(LIBDEST)/site-packages -f \ -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + ./$(BUILDPYTHON) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + ./$(BUILDPYTHON) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt # Create the PLATDIR source directory, if one wasn't distributed.. $(srcdir)/Lib/$(PLATDIR): @@ -1203,7 +1205,7 @@ find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name 'fficonfig.py' -exec rm -f {} ';' || true - -rm -f $(srcdir)/Lib/lib2to3/*Grammar*.pickle + -rm -f Lib/lib2to3/*Grammar*.pickle profile-removal: find . -name '*.gc??' -exec rm -f {} ';' diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -388,7 +388,7 @@ - Issue #15819: Make sure we can build Python out-of-tree from a readonly source directory. (Somewhat related to Issue #9860.) -- Issue #15645: Ensure 2to3 grammar pickles are properly installed. +- Issue #15822: Ensure 2to3 grammar pickles are properly installed. - Issue #15560: Fix building _sqlite3 extension on OS X with an SDK. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 04:08:56 2012 From: python-checkins at python.org (ned.deily) Date: Sun, 9 Sep 2012 04:08:56 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1ODIy?= =?utf-8?q?=3A_Fix_installation_of_lib2to3_grammar_pickles_to_ensure?= Message-ID: <3XDwmS3gQbzQNk@mail.python.org> http://hg.python.org/cpython/rev/adc5e6aca251 changeset: 78895:adc5e6aca251 branch: 3.2 parent: 78891:8c60bb098eff user: Ned Deily date: Sat Sep 08 18:50:56 2012 -0700 summary: Issue #15822: Fix installation of lib2to3 grammar pickles to ensure they are created in the install locations and with the proper timestamp. (Solution suggested by MvL) files: Lib/lib2to3/pgen2/driver.py | 17 +++++++++++++++++ Makefile.pre.in | 8 +++++--- Misc/NEWS | 2 +- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -138,3 +138,20 @@ if not os.path.exists(b): return True return os.path.getmtime(a) >= os.path.getmtime(b) + + +def main(*args): + """Main program, when run as a script: produce grammar pickle files. + + Calls load_grammar for each argument, a path to a grammar text file. + """ + if not args: + args = sys.argv[1:] + logging.basicConfig(level=logging.INFO, stream=sys.stdout, + format='%(message)s') + for gt in args: + load_grammar(gt, save=True, force=True) + return True + +if __name__ == "__main__": + sys.exit(int(not main())) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -945,8 +945,6 @@ unittest unittest/test \ curses pydoc_data $(MACHDEPS) libinstall: build_all $(srcdir)/Lib/$(PLATDIR) $(srcdir)/Modules/xxmodule.c - -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - ./$(BUILDPYTHON) -Wi -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" @for i in $(SCRIPTDIR) $(LIBDEST); \ do \ if test ! -d $(DESTDIR)$$i; then \ @@ -1024,6 +1022,10 @@ ./$(BUILDPYTHON) -Wi -O $(DESTDIR)$(LIBDEST)/compileall.py \ -d $(LIBDEST)/site-packages -f \ -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + ./$(BUILDPYTHON) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + ./$(BUILDPYTHON) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt # Create the PLATDIR source directory, if one wasn't distributed.. $(srcdir)/Lib/$(PLATDIR): @@ -1264,7 +1266,7 @@ find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name 'fficonfig.py' -exec rm -f {} ';' || true - -rm -f $(srcdir)/Lib/lib2to3/*Grammar*.pickle + -rm -f Lib/lib2to3/*Grammar*.pickle -rm -f Modules/_testembed profile-removal: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -525,7 +525,7 @@ - Issue #15819: Make sure we can build Python out-of-tree from a readonly source directory. (Somewhat related to Issue #9860.) -- Issue #15645: Ensure 2to3 grammar pickles are properly installed. +- Issue #15822: Ensure 2to3 grammar pickles are properly installed. - Issue #15560: Fix building _sqlite3 extension on OS X with an SDK. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 04:08:57 2012 From: python-checkins at python.org (ned.deily) Date: Sun, 9 Sep 2012 04:08:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_null_merge?= Message-ID: <3XDwmT6jh7zQMw@mail.python.org> http://hg.python.org/cpython/rev/23118b802f83 changeset: 78896:23118b802f83 parent: 78892:0c2bdd2c2032 parent: 78895:adc5e6aca251 user: Ned Deily date: Sat Sep 08 18:59:46 2012 -0700 summary: null merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 04:08:59 2012 From: python-checkins at python.org (ned.deily) Date: Sun, 9 Sep 2012 04:08:59 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315822=3A_Fix_inst?= =?utf-8?q?allation_of_lib2to3_grammar_pickles_to_ensure?= Message-ID: <3XDwmW2bfbzQPx@mail.python.org> http://hg.python.org/cpython/rev/a829889f96b0 changeset: 78897:a829889f96b0 user: Ned Deily date: Sat Sep 08 19:04:47 2012 -0700 summary: Issue #15822: Fix installation of lib2to3 grammar pickles to ensure they are created in the install locations and with the proper timestamp. (Solution suggested by MvL) files: Lib/lib2to3/pgen2/driver.py | 17 +++++++++++++++++ Makefile.pre.in | 8 +++++--- Misc/NEWS | 3 +++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -138,3 +138,20 @@ if not os.path.exists(b): return True return os.path.getmtime(a) >= os.path.getmtime(b) + + +def main(*args): + """Main program, when run as a script: produce grammar pickle files. + + Calls load_grammar for each argument, a path to a grammar text file. + """ + if not args: + args = sys.argv[1:] + logging.basicConfig(level=logging.INFO, stream=sys.stdout, + format='%(message)s') + for gt in args: + load_grammar(gt, save=True, force=True) + return True + +if __name__ == "__main__": + sys.exit(int(not main())) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1024,8 +1024,6 @@ venv venv/scripts venv/scripts/posix \ curses pydoc_data $(MACHDEPS) libinstall: build_all $(srcdir)/Lib/$(PLATDIR) $(srcdir)/Modules/xxmodule.c - -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - $(PYTHON_FOR_BUILD) -Wi -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" @for i in $(SCRIPTDIR) $(LIBDEST); \ do \ if test ! -d $(DESTDIR)$$i; then \ @@ -1103,6 +1101,10 @@ $(PYTHON_FOR_BUILD) -Wi -O $(DESTDIR)$(LIBDEST)/compileall.py \ -d $(LIBDEST)/site-packages -f \ -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt # Create the PLATDIR source directory, if one wasn't distributed.. $(srcdir)/Lib/$(PLATDIR): @@ -1347,7 +1349,7 @@ find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name 'fficonfig.py' -exec rm -f {} ';' || true - -rm -f $(srcdir)/Lib/lib2to3/*Grammar*.pickle + -rm -f Lib/lib2to3/*Grammar*.pickle -rm -f $(SYSCONFIGDATA) -rm -f Modules/_testembed Modules/_freeze_importlib diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -62,6 +62,9 @@ - Issue #15819: Make sure we can build Python out-of-tree from a readonly source directory. (Somewhat related to Issue #9860.) +- Issue #15822: Really ensure 2to3 grammar pickles are properly installed + (replaces fixes for Issue #15645). + Documentation ------------- -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Sep 9 06:03:49 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 09 Sep 2012 06:03:49 +0200 Subject: [Python-checkins] Daily reference leaks (0c2bdd2c2032): sum=3 Message-ID: results for 0c2bdd2c2032 on branch "default" -------------------------------------------- test_support leaked [1, 0, 0] references, sum=1 test_dbm leaked [0, 0, 2] references, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogoWyOAY', '-x'] From python-checkins at python.org Sun Sep 9 09:09:40 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 09:09:40 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Add_Daniel_Holth_to_commi?= =?utf-8?q?tter_list=2E?= Message-ID: <3XF3RS039jzQQl@mail.python.org> http://hg.python.org/devguide/rev/0554ac390c27 changeset: 546:0554ac390c27 user: Georg Brandl date: Sun Sep 09 09:10:12 2012 +0200 summary: Add Daniel Holth to committer list. files: developers.rst | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/developers.rst b/developers.rst --- a/developers.rst +++ b/developers.rst @@ -24,6 +24,8 @@ Permissions History ------------------- +- Daniel Holth was given push privileges on Sep 9 2012 by GFB, for PEP editing. + - Peter Moody was given push privileges on May 20 2012 by Antoine Pitrou for authorship and maintenance of the ipaddress module (accepted in PEP 3144 by Nick Coghlan). -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Sep 9 09:11:08 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 09:11:08 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Add_Eric_Snow=2E?= Message-ID: <3XF3T86SBbzQQl@mail.python.org> http://hg.python.org/devguide/rev/2b5d169f3554 changeset: 547:2b5d169f3554 user: Georg Brandl date: Sun Sep 09 09:11:42 2012 +0200 summary: Add Eric Snow. files: developers.rst | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/developers.rst b/developers.rst --- a/developers.rst +++ b/developers.rst @@ -26,9 +26,12 @@ - Daniel Holth was given push privileges on Sep 9 2012 by GFB, for PEP editing. -- Peter Moody was given push privileges on May 20 2012 by Antoine Pitrou - for authorship and maintenance of the ipaddress module (accepted in PEP - 3144 by Nick Coghlan). +- Eric Snow was given push privileges on Sep 5 2012 by Antoine Pitrou for + general contributions, on recommendation by Nick Coghlan. + +- Peter Moody was given push privileges on May 20 2012 by Antoine Pitrou for + authorship and maintenance of the ipaddress module (accepted in PEP 3144 by + Nick Coghlan). - Hynek Schlawack was given push privileges on May 14 2012 by Antoine Pitrou for general contributions. -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Sep 9 09:19:50 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 09:19:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Update_committers_list_lo?= =?utf-8?q?cation=2E?= Message-ID: <3XF3gB6HtHzQNv@mail.python.org> http://hg.python.org/devguide/rev/b40bfc99c54f changeset: 548:b40bfc99c54f user: Georg Brandl date: Sun Sep 09 09:20:23 2012 +0200 summary: Update committers list location. files: coredev.rst | 4 ++-- faq.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/coredev.rst b/coredev.rst --- a/coredev.rst +++ b/coredev.rst @@ -25,7 +25,7 @@ able to commit them without supervision. A complete list of core developer usernames can be found at -http://www.python.org/dev/committers. :ref:`developers` lists when and why +http://hg.python.org/committers.txt. :ref:`developers` lists when and why someone received commit privileges. @@ -68,7 +68,7 @@ This should match your username on the issue tracker. You can verify your commit access by looking at -http://www.python.org/dev/committers which lists all core developers by +http://hg.python.org/committers.txt which lists all core developers by username. If you want to practice, there is a `test repository `_ where you can freely commit and push any changes you like:: diff --git a/faq.rst b/faq.rst --- a/faq.rst +++ b/faq.rst @@ -96,7 +96,7 @@ On the `issue tracker`_, most core developers will have the Python logo appear next to their name. -.. _full list of developers: http://www.python.org/dev/committers +.. _full list of developers: http://hg.python.org/committers.txt What standards of behaviour are expected in these communication channels? -- Repository URL: http://hg.python.org/devguide From python-checkins at python.org Sun Sep 9 11:12:24 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:12:24 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?peps=3A_Remove_outdated_Windows_instr?= =?utf-8?q?uctions=2E?= Message-ID: <3XF6942JrlzQ79@mail.python.org> http://hg.python.org/peps/rev/33ad4b3e0d6f changeset: 4509:33ad4b3e0d6f user: Georg Brandl date: Sun Sep 09 11:12:29 2012 +0200 summary: Remove outdated Windows instructions. files: pep-0101.txt | 12 ++---------- 1 files changed, 2 insertions(+), 10 deletions(-) diff --git a/pep-0101.txt b/pep-0101.txt --- a/pep-0101.txt +++ b/pep-0101.txt @@ -600,16 +600,8 @@ only person routinely testing on Windows, and that Windows is simply a mess. - Repeat the testing for each target architecture. On XP/2003, try - both an Admin and a plain User (not Power User) account. If you - can, also test the installer on Windows 9x. - - WRT Step 5 above (verify the release media), since by the time - release files are ready to download the WE has generally run many - Windows tests on the installer he uploaded, he usually doesn't do - anything for Step 5 except a full byte-comparison ("fc /b" if - using a Windows shell) of the downloaded file against the file he - uploaded. + Repeat the testing for each target architecture. Try both an + Admin and a plain User (not Power User) account. Copyright -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Sun Sep 9 11:18:59 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:18:59 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315785=3A_Modify_w?= =?utf-8?q?indow=2Eget=5Fwch=28=29_API_of_the_curses_module=3A_return_a?= Message-ID: <3XF6Jg51zxzQYc@mail.python.org> http://hg.python.org/cpython/rev/23377e88487b changeset: 78898:23377e88487b parent: 78771:290a07e57797 user: Victor Stinner date: Wed Aug 29 01:40:57 2012 +0200 summary: Issue #15785: Modify window.get_wch() API of the curses module: return a character for most keys, and an integer for special keys, instead of always returning an integer. So it is now possible to distinguish special keys like keypad keys. files: Doc/library/curses.rst | 9 +++++---- Lib/test/test_curses.py | 12 +++++------- Misc/NEWS | 7 ++++++- Modules/_cursesmodule.c | 5 ++++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -869,8 +869,8 @@ .. method:: window.get_wch([y, x]) - Get a wide character. Like :meth:`getch`, but the integer returned is the - Unicode code point for the key pressed, so it can be passed to :func:`chr`. + Get a wide character. Return a character for most keys, or an integer for + function keys, keypad keys, and other special keys. .. versionadded:: 3.3 @@ -878,8 +878,9 @@ .. method:: window.getkey([y, x]) Get a character, returning a string instead of an integer, as :meth:`getch` - does. Function keys, keypad keys and so on return a multibyte string containing - the key name. In no-delay mode, an exception is raised if there is no input. + does. Function keys, keypad keys and other special keys return a multibyte + string containing the key name. In no-delay mode, an exception is raised if + there is no input. .. method:: window.getmaxyx() diff --git a/Lib/test/test_curses.py b/Lib/test/test_curses.py --- a/Lib/test/test_curses.py +++ b/Lib/test/test_curses.py @@ -267,8 +267,7 @@ def test_unget_wch(stdscr): if not hasattr(curses, 'unget_wch'): return - import locale - encoding = locale.getpreferredencoding() + encoding = stdscr.encoding for ch in ('a', '\xe9', '\u20ac', '\U0010FFFF'): try: ch.encode(encoding) @@ -277,18 +276,17 @@ try: curses.unget_wch(ch) except Exception as err: - raise Exception("unget_wch(%a) failed with locale encoding %s: %s" - % (ch, encoding, err)) + raise Exception("unget_wch(%a) failed with encoding %s: %s" + % (ch, stdscr.encoding, err)) read = stdscr.get_wch() - read = chr(read) if read != ch: raise AssertionError("%r != %r" % (read, ch)) code = ord(ch) curses.unget_wch(code) read = stdscr.get_wch() - if read != code: - raise AssertionError("%r != %r" % (read, code)) + if read != ch: + raise AssertionError("%r != %r" % (read, ch)) def test_issue10570(): b = curses.tparm(curses.tigetstr("cup"), 5, 3) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,11 @@ Library ------- +- Issue #15785: Modify window.get_wch() API of the curses module: return + a character for most keys, and an integer for special keys, instead of + always returning an integer. So it is now possible to distinguish special + keys like keypad keys. + What's New in Python 3.3.0 Release Candidate 1? =============================================== @@ -23,7 +28,7 @@ ----------------- - Issue #15573: memoryview comparisons are now performed by value with full - support for any valid struct module format definition. + support for any valid struct module format definition. - Issue #15316: When an item in the fromlist for __import__ doesn't exist, don't raise an error, but if an exception is raised as part of an import do diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -1203,7 +1203,10 @@ PyErr_SetString(PyCursesError, "no input"); return NULL; } - return PyLong_FromLong(rtn); + if (ct == KEY_CODE_YES) + return PyLong_FromLong(rtn); + else + return PyUnicode_FromOrdinal(rtn); } #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:01 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:01 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315784=3A_Modify_O?= =?utf-8?q?SError=2E=5F=5Fstr=5F=5F=28=29_to_better_distinguish_between?= Message-ID: <3XF6Jj3zqRzQCL@mail.python.org> http://hg.python.org/cpython/rev/4e941113e4fa changeset: 78899:4e941113e4fa user: Richard Oudkerk date: Tue Aug 28 19:33:26 2012 +0100 summary: Issue #15784: Modify OSError.__str__() to better distinguish between errno error numbers and Windows error numbers. files: Lib/test/test_exceptions.py | 4 ++-- Misc/NEWS | 3 +++ Objects/exceptions.c | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -216,14 +216,14 @@ self.assertEqual(w.winerror, 3) self.assertEqual(w.strerror, 'foo') self.assertEqual(w.filename, 'bar') - self.assertEqual(str(w), "[Error 3] foo: 'bar'") + self.assertEqual(str(w), "[WinError 3] foo: 'bar'") # Unknown win error becomes EINVAL (22) w = OSError(0, 'foo', None, 1001) self.assertEqual(w.errno, 22) self.assertEqual(w.winerror, 1001) self.assertEqual(w.strerror, 'foo') self.assertEqual(w.filename, None) - self.assertEqual(str(w), "[Error 1001] foo") + self.assertEqual(str(w), "[WinError 1001] foo") # Non-numeric "errno" w = OSError('bar', 'foo') self.assertEqual(w.errno, 'bar') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #15784: Modify OSError.__str__() to better distinguish between + errno error numbers and Windows error numbers. + Library ------- diff --git a/Objects/exceptions.c b/Objects/exceptions.c --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -1016,12 +1016,12 @@ #ifdef MS_WINDOWS /* If available, winerror has the priority over myerrno */ if (self->winerror && self->filename) - return PyUnicode_FromFormat("[Error %S] %S: %R", + return PyUnicode_FromFormat("[WinError %S] %S: %R", self->winerror ? self->winerror: Py_None, self->strerror ? self->strerror: Py_None, self->filename); if (self->winerror && self->strerror) - return PyUnicode_FromFormat("[Error %S] %S", + return PyUnicode_FromFormat("[WinError %S] %S", self->winerror ? self->winerror: Py_None, self->strerror ? self->strerror: Py_None); #endif -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:03 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:03 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315781=3A_Fix_two_?= =?utf-8?q?small_race_conditions_in_import=27s_module_locking=2E?= Message-ID: <3XF6Jl0pNnzQY4@mail.python.org> http://hg.python.org/cpython/rev/85070f284fd2 changeset: 78900:85070f284fd2 user: Antoine Pitrou date: Tue Aug 28 00:24:52 2012 +0200 summary: Issue #15781: Fix two small race conditions in import's module locking. files: Lib/importlib/_bootstrap.py | 10 +- Lib/test/test_threaded_import.py | 12 +- Misc/NEWS | 2 + Python/import.c | 6 +- Python/importlib.h | 7302 +++++++++-------- 5 files changed, 3678 insertions(+), 3654 deletions(-) diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py +++ b/Lib/importlib/_bootstrap.py @@ -268,8 +268,10 @@ Should only be called with the import lock taken.""" lock = None - if name in _module_locks: + try: lock = _module_locks[name]() + except KeyError: + pass if lock is None: if _thread is None: lock = _DummyModuleLock(name) @@ -543,6 +545,9 @@ # implicitly imports 'locale' and would otherwise trigger an # infinite loop. module = new_module(fullname) + # This must be done before putting the module in sys.modules + # (otherwise an optimization shortcut in import.c becomes wrong) + module.__initializing__ = True sys.modules[fullname] = module module.__loader__ = self try: @@ -554,8 +559,9 @@ module.__package__ = fullname else: module.__package__ = fullname.rpartition('.')[0] + else: + module.__initializing__ = True try: - module.__initializing__ = True # If __package__ was not set above, __import__() will do it later. return fxn(self, module, *args, **kwargs) except: diff --git a/Lib/test/test_threaded_import.py b/Lib/test/test_threaded_import.py --- a/Lib/test/test_threaded_import.py +++ b/Lib/test/test_threaded_import.py @@ -224,7 +224,17 @@ @reap_threads def test_main(): - run_unittest(ThreadedImportTests) + old_switchinterval = None + try: + old_switchinterval = sys.getswitchinterval() + sys.setswitchinterval(0.00000001) + except AttributeError: + pass + try: + run_unittest(ThreadedImportTests) + finally: + if old_switchinterval is not None: + sys.setswitchinterval(old_switchinterval) if __name__ == "__main__": test_main() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -13,6 +13,8 @@ - Issue #15784: Modify OSError.__str__() to better distinguish between errno error numbers and Windows error numbers. +- Issue #15781: Fix two small race conditions in import's module locking. + Library ------- diff --git a/Python/import.c b/Python/import.c --- a/Python/import.c +++ b/Python/import.c @@ -1408,7 +1408,11 @@ int initializing = 0; Py_INCREF(mod); - /* Only call _bootstrap._lock_unlock_module() if __initializing__ is true. */ + /* Optimization: only call _bootstrap._lock_unlock_module() if + __initializing__ is true. + NOTE: because of this, __initializing__ must be set *before* + stuffing the new module in sys.modules. + */ value = _PyObject_GetAttrId(mod, &PyId___initializing__); if (value == NULL) PyErr_Clear(); diff --git a/Python/importlib.h b/Python/importlib.h --- a/Python/importlib.h +++ b/Python/importlib.h [stripped] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:04 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:04 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315340=3A_Fix_impo?= =?utf-8?q?rting_the_random_module_when_/dev/urandom_cannot_be?= Message-ID: <3XF6Jm45F5zQY8@mail.python.org> http://hg.python.org/cpython/rev/6a782496f90a changeset: 78901:6a782496f90a user: Antoine Pitrou date: Fri Sep 07 23:49:07 2012 +0200 summary: Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. files: Misc/NEWS | 3 +++ Python/random.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,6 +18,9 @@ Library ------- +- Issue #15340: Fix importing the random module when /dev/urandom cannot + be opened. This was a regression caused by the hash randomization patch. + - Issue #15785: Modify window.get_wch() API of the curses module: return a character for most keys, and an integer for special keys, instead of always returning an integer. So it is now possible to distinguish special diff --git a/Python/random.c b/Python/random.c --- a/Python/random.c +++ b/Python/random.c @@ -165,7 +165,8 @@ Py_END_ALLOW_THREADS if (fd < 0) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/dev/urandom"); + PyErr_SetString(PyExc_NotImplementedError, + "/dev/urandom (or equivalent) not found"); return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:06 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315828=3A_Restore_?= =?utf-8?q?support_for_C_extension_modules_in_imp=2Eload=5Fmodule=28=29?= Message-ID: <3XF6Jp3DwBzQYl@mail.python.org> http://hg.python.org/cpython/rev/4f6f59303146 changeset: 78902:4f6f59303146 user: Nick Coghlan date: Sat Sep 01 00:13:45 2012 +1000 summary: Issue #15828: Restore support for C extension modules in imp.load_module() files: Lib/imp.py | 6 ++++-- Lib/test/test_imp.py | 29 +++++++++++++++++++++++++++++ Lib/test/test_import.py | 19 ------------------- Misc/NEWS | 2 ++ 4 files changed, 35 insertions(+), 21 deletions(-) diff --git a/Lib/imp.py b/Lib/imp.py --- a/Lib/imp.py +++ b/Lib/imp.py @@ -153,13 +153,15 @@ warnings.simplefilter('ignore') if mode and (not mode.startswith(('r', 'U')) or '+' in mode): raise ValueError('invalid file open mode {!r}'.format(mode)) - elif file is None and type_ in {PY_SOURCE, PY_COMPILED}: + elif file is None and type_ in {PY_SOURCE, PY_COMPILED, C_EXTENSION}: msg = 'file object required for import (type code {})'.format(type_) raise ValueError(msg) elif type_ == PY_SOURCE: return load_source(name, filename, file) elif type_ == PY_COMPILED: return load_compiled(name, filename, file) + elif type_ == C_EXTENSION: + return load_dynamic(name, filename, file) elif type_ == PKG_DIRECTORY: return load_package(name, filename) elif type_ == C_BUILTIN: @@ -167,7 +169,7 @@ elif type_ == PY_FROZEN: return init_frozen(name) else: - msg = "Don't know how to import {} (type code {}".format(name, type_) + msg = "Don't know how to import {} (type code {})".format(name, type_) raise ImportError(msg, name=name) diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -186,6 +186,35 @@ self.assertRaises(SyntaxError, imp.find_module, "badsyntax_pep3120", [path]) + def test_load_from_source(self): + # Verify that the imp module can correctly load and find .py files + # XXX (ncoghlan): It would be nice to use support.CleanImport + # here, but that breaks because the os module registers some + # handlers in copy_reg on import. Since CleanImport doesn't + # revert that registration, the module is left in a broken + # state after reversion. Reinitialising the module contents + # and just reverting os.environ to its previous state is an OK + # workaround + orig_path = os.path + orig_getenv = os.getenv + with support.EnvironmentVarGuard(): + x = imp.find_module("os") + self.addCleanup(x[0].close) + new_os = imp.load_module("os", *x) + self.assertIs(os, new_os) + self.assertIs(orig_path, new_os.path) + self.assertIsNot(orig_getenv, new_os.getenv) + + @support.cpython_only + def test_issue15828_load_extensions(self): + # Issue 15828 picked up that the adapter between the old imp API + # and importlib couldn't handle C extensions + example = "_heapq" + x = imp.find_module(example) + self.addCleanup(x[0].close) + mod = imp.load_module(example, *x) + self.assertEqual(mod.__name__, example) + def test_load_dynamic_ImportError_path(self): # Issue #1559549 added `name` and `path` attributes to ImportError # in order to provide better detail. Issue #10854 implemented those diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py --- a/Lib/test/test_import.py +++ b/Lib/test/test_import.py @@ -149,25 +149,6 @@ self.assertEqual(oct(stat.S_IMODE(stat_info.st_mode)), oct(mode)) - def test_imp_module(self): - # Verify that the imp module can correctly load and find .py files - # XXX (ncoghlan): It would be nice to use support.CleanImport - # here, but that breaks because the os module registers some - # handlers in copy_reg on import. Since CleanImport doesn't - # revert that registration, the module is left in a broken - # state after reversion. Reinitialising the module contents - # and just reverting os.environ to its previous state is an OK - # workaround - orig_path = os.path - orig_getenv = os.getenv - with EnvironmentVarGuard(): - x = imp.find_module("os") - self.addCleanup(x[0].close) - new_os = imp.load_module("os", *x) - self.assertIs(os, new_os) - self.assertIs(orig_path, new_os.path) - self.assertIsNot(orig_getenv, new_os.getenv) - def test_bug7732(self): source = TESTFN + '.py' os.mkdir(source) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,6 +18,8 @@ Library ------- +- Issue #15828: Restore support for C extensions in imp.load_module(). + - Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:07 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315828=3A_Don=27t_?= =?utf-8?q?try_to_close_a_file_if_imp=2Efind=5Fmodule=28=29_doesn=27t?= Message-ID: <3XF6Jq6JXgzQWD@mail.python.org> http://hg.python.org/cpython/rev/a4a9c5717204 changeset: 78903:a4a9c5717204 user: Brett Cannon date: Fri Aug 31 11:31:20 2012 -0400 summary: Issue #15828: Don't try to close a file if imp.find_module() doesn't return one. files: Lib/test/test_imp.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_imp.py b/Lib/test/test_imp.py --- a/Lib/test/test_imp.py +++ b/Lib/test/test_imp.py @@ -211,7 +211,9 @@ # and importlib couldn't handle C extensions example = "_heapq" x = imp.find_module(example) - self.addCleanup(x[0].close) + file_ = x[0] + if file_ is not None: + self.addCleanup(file_.close) mod = imp.load_module(example, *x) self.assertEqual(mod.__name__, example) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:09 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:09 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2314223=3A_Fix_wind?= =?utf-8?q?ow=2Eaddch=28curses=2EACS=5FHLINE=29?= Message-ID: <3XF6Js2RqRzQYq@mail.python.org> http://hg.python.org/cpython/rev/d6d632f254ee changeset: 78904:d6d632f254ee user: Victor Stinner date: Sat Sep 01 15:00:34 2012 +0200 summary: Close #14223: Fix window.addch(curses.ACS_HLINE) Fix window.addch() of the curses module for special characters like curses.ACS_HLINE: the Python function addch(int) and addch(bytes) is now calling the C function waddch()/mvwaddch() (as it was done in Python 3.2), instead of wadd_wch()/mvwadd_wch(). The Python function addch(str) is still calling the C function wadd_wch()/mvwadd_wch() if the Python curses is linked to libncursesw. files: Misc/NEWS | 7 +++++ Modules/_cursesmodule.c | 34 +++++----------------------- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -28,6 +28,13 @@ always returning an integer. So it is now possible to distinguish special keys like keypad keys. +- Issue #14223: Fix window.addch() of the curses module for special characters + like curses.ACS_HLINE: the Python function addch(int) and addch(bytes) is now + calling the C function waddch()/mvwaddch() (as it was done in Python 3.2), + instead of wadd_wch()/mvwadd_wch(). The Python function addch(str) is still + calling the C function wadd_wch()/mvwadd_wch() if the Python curses is linked + to libncursesw. + What's New in Python 3.3.0 Release Candidate 1? =============================================== diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c --- a/Modules/_cursesmodule.c +++ b/Modules/_cursesmodule.c @@ -280,7 +280,6 @@ #endif ) { - int ret = 0; long value; #ifdef HAVE_NCURSESW wchar_t buffer[2]; @@ -304,7 +303,6 @@ } else if(PyBytes_Check(obj) && PyBytes_Size(obj) == 1) { value = (unsigned char)PyBytes_AsString(obj)[0]; - ret = 1; } else if (PyLong_CheckExact(obj)) { int overflow; @@ -314,11 +312,6 @@ "int doesn't fit in long"); return 0; } -#ifdef HAVE_NCURSESW - ret = 2; -#else - ret = 1; -#endif } else { PyErr_Format(PyExc_TypeError, @@ -326,27 +319,14 @@ Py_TYPE(obj)->tp_name); return 0; } -#ifdef HAVE_NCURSESW - if (ret == 2) { - memset(wch->chars, 0, sizeof(wch->chars)); - wch->chars[0] = (wchar_t)value; - if ((long)wch->chars[0] != value) { - PyErr_Format(PyExc_OverflowError, - "character doesn't fit in wchar_t"); - return 0; - } + + *ch = (chtype)value; + if ((long)*ch != value) { + PyErr_Format(PyExc_OverflowError, + "byte doesn't fit in chtype"); + return 0; } - else -#endif - { - *ch = (chtype)value; - if ((long)*ch != value) { - PyErr_Format(PyExc_OverflowError, - "byte doesn't fit in chtype"); - return 0; - } - } - return ret; + return 1; } /* Convert an object to a byte string (char*) or a wide character string -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:10 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:10 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Compile_=5Fdecimal_without?= =?utf-8?q?_asserts_and_update_benchmark_results=2E?= Message-ID: <3XF6Jt5gyPzQXl@mail.python.org> http://hg.python.org/cpython/rev/0e6e86a6bfb7 changeset: 78905:0e6e86a6bfb7 user: Stefan Krah date: Sat Sep 01 14:21:22 2012 +0200 summary: Compile _decimal without asserts and update benchmark results. files: Doc/whatsnew/3.3.rst | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1119,7 +1119,7 @@ +---------+-------------+--------------+-------------+ | | decimal.py | _decimal | speedup | +=========+=============+==============+=============+ - | pi | 38.89s | 0.38s | 100x | + | pi | 42.02 | 0.345 | 120x | +---------+-------------+--------------+-------------+ | telco | 172.19s | 5.68s | 30x | +---------+-------------+--------------+-------------+ diff --git a/setup.py b/setup.py --- a/setup.py +++ b/setup.py @@ -1897,7 +1897,7 @@ def _decimal_ext(self): extra_compile_args = [] - undef_macros = ['NDEBUG'] + undef_macros = [] if '--with-system-libmpdec' in sysconfig.get_config_var("CONFIG_ARGS"): include_dirs = [] libraries = ['mpdec'] -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:12 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:12 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Add_missing_unit=2E?= Message-ID: <3XF6Jw2VTfzQYn@mail.python.org> http://hg.python.org/cpython/rev/de409254d61b changeset: 78906:de409254d61b user: Stefan Krah date: Sat Sep 01 14:27:51 2012 +0200 summary: Add missing unit. files: Doc/whatsnew/3.3.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1119,7 +1119,7 @@ +---------+-------------+--------------+-------------+ | | decimal.py | _decimal | speedup | +=========+=============+==============+=============+ - | pi | 42.02 | 0.345 | 120x | + | pi | 42.02s | 0.345s | 120x | +---------+-------------+--------------+-------------+ | telco | 172.19s | 5.68s | 30x | +---------+-------------+--------------+-------------+ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:13 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:13 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315724=3A_Add_vers?= =?utf-8?q?ionchanged_tags_to_the_memoryview_documentation=2E?= Message-ID: <3XF6Jx6flHzQYy@mail.python.org> http://hg.python.org/cpython/rev/144d649764cf changeset: 78907:144d649764cf user: Stefan Krah date: Thu Aug 30 12:09:09 2012 +0200 summary: Issue #15724: Add versionchanged tags to the memoryview documentation. files: Doc/library/stdtypes.rst | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2450,6 +2450,8 @@ ``v == w`` for memoryview objects. .. versionchanged:: 3.3 + Previous versions compared the raw memory disregarding the item format + and the logical array structure. .. method:: tobytes() @@ -2479,8 +2481,10 @@ >>> m.tolist() [1.1, 2.2, 3.3] - :meth:`tolist` is currently restricted to single character native formats - in :mod:`struct` module syntax. + .. versionchanged:: 3.3 + :meth:`tolist` now supports all single character native formats in + :mod:`struct` module syntax as well as multi-dimensional + representations. .. method:: release() @@ -2664,6 +2668,10 @@ arbitrary format strings, but some methods (e.g. :meth:`tolist`) are restricted to native single element formats. + .. versionchanged:: 3.3 + format ``'B'`` is now handled according to the struct module syntax. + This means that ``memoryview(b'abc')[0] == b'abc'[0] == 97``. + .. attribute:: itemsize The size in bytes of each element of the memoryview:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:15 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:15 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315814=3A_Document?= =?utf-8?q?_planned_restrictions_for_memoryview_hashes_in_3=2E3=2E1=2E?= Message-ID: <3XF6Jz45V4zQY5@mail.python.org> http://hg.python.org/cpython/rev/7734eb2707a1 changeset: 78908:7734eb2707a1 user: Stefan Krah date: Sat Sep 01 14:34:45 2012 +0200 summary: Issue #15814: Document planned restrictions for memoryview hashes in 3.3.1. files: Doc/library/stdtypes.rst | 24 ++++++++---------------- 1 files changed, 8 insertions(+), 16 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2376,8 +2376,8 @@ >>> data bytearray(b'z1spam') - Memoryviews of hashable (read-only) types are also hashable. The hash - is defined as ``hash(m) == hash(m.tobytes())``:: + Memoryviews of hashable (read-only) types with formats 'B', 'b' or 'c' + are also hashable. The hash is defined as ``hash(m) == hash(m.tobytes())``:: >>> v = memoryview(b'abcefg') >>> hash(v) == hash(b'abcefg') @@ -2387,21 +2387,13 @@ >>> hash(v[::-2]) == hash(b'abcefg'[::-2]) True - Hashing of multi-dimensional objects is supported:: - - >>> buf = bytes(list(range(12))) - >>> x = memoryview(buf) - >>> y = x.cast('B', shape=[2,2,3]) - >>> x.tolist() - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] - >>> y.tolist() - [[[0, 1, 2], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]] - >>> hash(x) == hash(y) == hash(y.tobytes()) - True - .. versionchanged:: 3.3 - Memoryview objects are now hashable. - + Memoryview objects with formats 'B', 'b' or 'c' are now hashable. + + .. note:: + Hashing of memoryviews with formats other than 'B', 'b' or 'c' is + possible in version 3.3.0, but will raise an error in 3.3.1 in order + to be compatible with the new memoryview equality definition. :class:`memoryview` has several methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:17 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:17 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Closes_=2310650=3A_Depreca?= =?utf-8?q?te_the_watchexp_parameter_of_Decimal=2Equantize=28=29=2E?= Message-ID: <3XF6K11jdkzQYq@mail.python.org> http://hg.python.org/cpython/rev/e4ca4edee8bd changeset: 78909:e4ca4edee8bd user: Stefan Krah date: Thu Aug 30 12:33:55 2012 +0200 summary: Closes #10650: Deprecate the watchexp parameter of Decimal.quantize(). files: Doc/library/decimal.rst | 5 +++++ Doc/whatsnew/3.3.rst | 4 ++++ Misc/NEWS | 3 +++ 3 files changed, 12 insertions(+), 0 deletions(-) diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -737,6 +737,11 @@ resulting exponent is greater than :attr:`Emax` or less than :attr:`Etiny`. + .. deprecated:: 3.3 + *watchexp* is an implementation detail from the pure Python version + and is not present in the C version. It will be removed in version + 3.4, where it defaults to ``True``. + .. method:: radix() Return ``Decimal(10)``, the radix (base) in which the :class:`Decimal` diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -1190,6 +1190,10 @@ changed to match the order displayed by :func:`repr`. +* The ``watchexp`` parameter in the :meth:`~decimal.Decimal.quantize` method + is deprecated. + + ftplib ------ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -23,6 +23,9 @@ - Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. +- Issue #10650: Deprecate the watchexp parameter of the Decimal.quantize() + method. + - Issue #15785: Modify window.get_wch() API of the curses module: return a character for most keys, and an integer for special keys, instead of always returning an integer. So it is now possible to distinguish special -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:18 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:18 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_bug_with_argparse=2EPa?= =?utf-8?q?rser=2Eparse=5Fargs=28*args=29?= Message-ID: <3XF6K24xHxzQQF@mail.python.org> http://hg.python.org/cpython/rev/8c2e87aeb707 changeset: 78910:8c2e87aeb707 user: Zbigniew J??drzejewski-Szmek date: Sun Sep 02 14:59:19 2012 +0200 summary: Fix bug with argparse.Parser.parse_args(*args) files: Lib/argparse.py | 5 ++++- Lib/test/test_argparse.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1709,9 +1709,12 @@ return args def parse_known_args(self, args=None, namespace=None): - # args default to the system args if args is None: + # args default to the system args args = _sys.argv[1:] + else: + # make sure that args are mutable + args = list(args) # default Namespace built from parser defaults if namespace is None: diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4565,6 +4565,24 @@ class TestParseKnownArgs(TestCase): + def test_arguments_tuple(self): + parser = argparse.ArgumentParser() + parser.parse_args(()) + + def test_arguments_list(self): + parser = argparse.ArgumentParser() + parser.parse_args([]) + + def test_arguments_tuple_positional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x') + parser.parse_args(('x',)) + + def test_arguments_list_positional(self): + parser = argparse.ArgumentParser() + parser.add_argument('x') + parser.parse_args(['x']) + def test_optionals(self): parser = argparse.ArgumentParser() parser.add_argument('--foo') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:20 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:20 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Changelog_entry_for_8c2e87?= =?utf-8?q?aeb707=2E?= Message-ID: <3XF6K411SszQYn@mail.python.org> http://hg.python.org/cpython/rev/514007be0874 changeset: 78911:514007be0874 user: Georg Brandl date: Sat Sep 08 07:58:37 2012 +0200 summary: Changelog entry for 8c2e87aeb707. files: Misc/NEWS | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -18,6 +18,9 @@ Library ------- +- Issue #15847: Fix a regression in argparse, which did not accept tuples + as argument lists anymore. + - Issue #15828: Restore support for C extensions in imp.load_module(). - Issue #15340: Fix importing the random module when /dev/urandom cannot -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:21 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:21 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2313992=3A_The_tras?= =?utf-8?q?hcan_mechanism_is_now_thread-safe=2E__This_eliminates?= Message-ID: <3XF6K570s9zQZ5@mail.python.org> http://hg.python.org/cpython/rev/5aa1bc2f00ad changeset: 78912:5aa1bc2f00ad user: Antoine Pitrou date: Thu Sep 06 00:59:49 2012 +0200 summary: Issue #13992: The trashcan mechanism is now thread-safe. This eliminates sporadic crashes in multi-thread programs when several long deallocator chains ran concurrently and involved subclasses of built-in container types. Because of this change, a couple extension modules compiled for 3.2.4 (those which use the trashcan mechanism, despite it being undocumented) will not be loadable by 3.2.3 and earlier. However, extension modules compiled for 3.2.3 and earlier will be loadable by 3.2.4. files: Include/object.h | 27 ++++++++---- Include/pystate.h | 3 + Lib/test/test_gc.py | 69 ++++++++++++++++++++++++++++++++ Misc/NEWS | 5 ++ Objects/object.c | 37 +++++++++++++++++ Objects/typeobject.c | 5 ++ Python/pystate.c | 3 + 7 files changed, 140 insertions(+), 9 deletions(-) diff --git a/Include/object.h b/Include/object.h --- a/Include/object.h +++ b/Include/object.h @@ -961,24 +961,33 @@ with the call stack never exceeding a depth of PyTrash_UNWIND_LEVEL. */ +/* This is the old private API, invoked by the macros before 3.2.4. + Kept for binary compatibility of extensions. */ PyAPI_FUNC(void) _PyTrash_deposit_object(PyObject*); PyAPI_FUNC(void) _PyTrash_destroy_chain(void); PyAPI_DATA(int) _PyTrash_delete_nesting; PyAPI_DATA(PyObject *) _PyTrash_delete_later; +/* The new thread-safe private API, invoked by the macros below. */ +PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyObject*); +PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(void); + #define PyTrash_UNWIND_LEVEL 50 #define Py_TRASHCAN_SAFE_BEGIN(op) \ - if (_PyTrash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ - ++_PyTrash_delete_nesting; - /* The body of the deallocator is here. */ + do { \ + PyThreadState *_tstate = PyThreadState_GET(); \ + if (_tstate->trash_delete_nesting < PyTrash_UNWIND_LEVEL) { \ + ++_tstate->trash_delete_nesting; + /* The body of the deallocator is here. */ #define Py_TRASHCAN_SAFE_END(op) \ - --_PyTrash_delete_nesting; \ - if (_PyTrash_delete_later && _PyTrash_delete_nesting <= 0) \ - _PyTrash_destroy_chain(); \ - } \ - else \ - _PyTrash_deposit_object((PyObject*)op); + --_tstate->trash_delete_nesting; \ + if (_tstate->trash_delete_later && _tstate->trash_delete_nesting <= 0) \ + _PyTrash_thread_destroy_chain(); \ + } \ + else \ + _PyTrash_thread_deposit_object((PyObject*)op); \ + } while (0); #ifndef Py_LIMITED_API PyAPI_FUNC(void) diff --git a/Include/pystate.h b/Include/pystate.h --- a/Include/pystate.h +++ b/Include/pystate.h @@ -114,6 +114,9 @@ PyObject *async_exc; /* Asynchronous exception to raise */ long thread_id; /* Thread id where this tstate was created */ + int trash_delete_nesting; + PyObject *trash_delete_later; + /* XXX signal handlers should also be here */ } PyThreadState; diff --git a/Lib/test/test_gc.py b/Lib/test/test_gc.py --- a/Lib/test/test_gc.py +++ b/Lib/test/test_gc.py @@ -2,9 +2,15 @@ from test.support import (verbose, refcount_test, run_unittest, strip_python_stderr) import sys +import time import gc import weakref +try: + import threading +except ImportError: + threading = None + ### Support code ############################################################################### @@ -328,6 +334,69 @@ v = {1: v, 2: Ouch()} gc.disable() + @unittest.skipUnless(threading, "test meaningless on builds without threads") + def test_trashcan_threads(self): + # Issue #13992: trashcan mechanism should be thread-safe + NESTING = 60 + N_THREADS = 2 + + def sleeper_gen(): + """A generator that releases the GIL when closed or dealloc'ed.""" + try: + yield + finally: + time.sleep(0.000001) + + class C(list): + # Appending to a list is atomic, which avoids the use of a lock. + inits = [] + dels = [] + def __init__(self, alist): + self[:] = alist + C.inits.append(None) + def __del__(self): + # This __del__ is called by subtype_dealloc(). + C.dels.append(None) + # `g` will release the GIL when garbage-collected. This + # helps assert subtype_dealloc's behaviour when threads + # switch in the middle of it. + g = sleeper_gen() + next(g) + # Now that __del__ is finished, subtype_dealloc will proceed + # to call list_dealloc, which also uses the trashcan mechanism. + + def make_nested(): + """Create a sufficiently nested container object so that the + trashcan mechanism is invoked when deallocating it.""" + x = C([]) + for i in range(NESTING): + x = [C([x])] + del x + + def run_thread(): + """Exercise make_nested() in a loop.""" + while not exit: + make_nested() + + old_switchinterval = sys.getswitchinterval() + sys.setswitchinterval(1e-5) + try: + exit = False + threads = [] + for i in range(N_THREADS): + t = threading.Thread(target=run_thread) + threads.append(t) + for t in threads: + t.start() + time.sleep(1.0) + exit = True + for t in threads: + t.join() + finally: + sys.setswitchinterval(old_switchinterval) + gc.collect() + self.assertEqual(len(C.inits), len(C.dels)) + def test_boom(self): class Boom: def __getattr__(self, someattribute): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,11 @@ Core and Builtins ----------------- +- Issue #13992: The trashcan mechanism is now thread-safe. This eliminates + sporadic crashes in multi-thread programs when several long deallocator + chains ran concurrently and involved subclasses of built-in container + types. + - Issue #15784: Modify OSError.__str__() to better distinguish between errno error numbers and Windows error numbers. diff --git a/Objects/object.c b/Objects/object.c --- a/Objects/object.c +++ b/Objects/object.c @@ -1954,6 +1954,18 @@ _PyTrash_delete_later = op; } +/* The equivalent API, using per-thread state recursion info */ +void +_PyTrash_thread_deposit_object(PyObject *op) +{ + PyThreadState *tstate = PyThreadState_GET(); + assert(PyObject_IS_GC(op)); + assert(_Py_AS_GC(op)->gc.gc_refs == _PyGC_REFS_UNTRACKED); + assert(op->ob_refcnt == 0); + _Py_AS_GC(op)->gc.gc_prev = (PyGC_Head *) tstate->trash_delete_later; + tstate->trash_delete_later = op; +} + /* Dealloccate all the objects in the _PyTrash_delete_later list. Called when * the call-stack unwinds again. */ @@ -1980,6 +1992,31 @@ } } +/* The equivalent API, using per-thread state recursion info */ +void +_PyTrash_thread_destroy_chain(void) +{ + PyThreadState *tstate = PyThreadState_GET(); + while (tstate->trash_delete_later) { + PyObject *op = tstate->trash_delete_later; + destructor dealloc = Py_TYPE(op)->tp_dealloc; + + tstate->trash_delete_later = + (PyObject*) _Py_AS_GC(op)->gc.gc_prev; + + /* Call the deallocator directly. This used to try to + * fool Py_DECREF into calling it indirectly, but + * Py_DECREF was already called on this object, and in + * assorted non-release builds calling Py_DECREF again ends + * up distorting allocation statistics. + */ + assert(op->ob_refcnt == 0); + ++tstate->trash_delete_nesting; + (*dealloc)(op); + --tstate->trash_delete_nesting; + } +} + #ifndef Py_TRACE_REFS /* For Py_LIMITED_API, we need an out-of-line version of _Py_Dealloc. Define this here, so we can undefine the macro. */ diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -891,6 +891,7 @@ { PyTypeObject *type, *base; destructor basedealloc; + PyThreadState *tstate = PyThreadState_GET(); /* Extract the type; we expect it to be a heap type */ type = Py_TYPE(self); @@ -940,8 +941,10 @@ /* See explanation at end of function for full disclosure */ PyObject_GC_UnTrack(self); ++_PyTrash_delete_nesting; + ++ tstate->trash_delete_nesting; Py_TRASHCAN_SAFE_BEGIN(self); --_PyTrash_delete_nesting; + -- tstate->trash_delete_nesting; /* DO NOT restore GC tracking at this point. weakref callbacks * (if any, and whether directly here or indirectly in something we * call) may trigger GC, and if self is tracked at that point, it @@ -1020,8 +1023,10 @@ endlabel: ++_PyTrash_delete_nesting; + ++ tstate->trash_delete_nesting; Py_TRASHCAN_SAFE_END(self); --_PyTrash_delete_nesting; + -- tstate->trash_delete_nesting; /* Explanation of the weirdness around the trashcan macros: diff --git a/Python/pystate.c b/Python/pystate.c --- a/Python/pystate.c +++ b/Python/pystate.c @@ -206,6 +206,9 @@ tstate->c_profileobj = NULL; tstate->c_traceobj = NULL; + tstate->trash_delete_nesting = 0; + tstate->trash_delete_later = NULL; + if (init) _PyThreadState_Init(tstate); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:23 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:23 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315822=3A_Fix_inst?= =?utf-8?q?allation_of_lib2to3_grammar_pickles_to_ensure?= Message-ID: <3XF6K737GBzQZ5@mail.python.org> http://hg.python.org/cpython/rev/411d500e56a1 changeset: 78913:411d500e56a1 user: Ned Deily date: Sat Sep 08 19:04:47 2012 -0700 summary: Issue #15822: Fix installation of lib2to3 grammar pickles to ensure they are created in the install locations and with the proper timestamp. (Solution suggested by MvL) files: Lib/lib2to3/pgen2/driver.py | 17 +++++++++++++++++ Makefile.pre.in | 8 +++++--- Misc/NEWS | 3 +++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Lib/lib2to3/pgen2/driver.py b/Lib/lib2to3/pgen2/driver.py --- a/Lib/lib2to3/pgen2/driver.py +++ b/Lib/lib2to3/pgen2/driver.py @@ -138,3 +138,20 @@ if not os.path.exists(b): return True return os.path.getmtime(a) >= os.path.getmtime(b) + + +def main(*args): + """Main program, when run as a script: produce grammar pickle files. + + Calls load_grammar for each argument, a path to a grammar text file. + """ + if not args: + args = sys.argv[1:] + logging.basicConfig(level=logging.INFO, stream=sys.stdout, + format='%(message)s') + for gt in args: + load_grammar(gt, save=True, force=True) + return True + +if __name__ == "__main__": + sys.exit(int(not main())) diff --git a/Makefile.pre.in b/Makefile.pre.in --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1017,8 +1017,6 @@ venv venv/scripts venv/scripts/posix \ curses pydoc_data $(MACHDEPS) libinstall: build_all $(srcdir)/Lib/$(PLATDIR) $(srcdir)/Modules/xxmodule.c - -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ - $(PYTHON_FOR_BUILD) -Wi -c "import lib2to3.pygram, lib2to3.patcomp;lib2to3.patcomp.PatternCompiler()" @for i in $(SCRIPTDIR) $(LIBDEST); \ do \ if test ! -d $(DESTDIR)$$i; then \ @@ -1096,6 +1094,10 @@ $(PYTHON_FOR_BUILD) -Wi -O $(DESTDIR)$(LIBDEST)/compileall.py \ -d $(LIBDEST)/site-packages -f \ -x badsyntax $(DESTDIR)$(LIBDEST)/site-packages + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/Grammar.txt + -PYTHONPATH=$(DESTDIR)$(LIBDEST) $(RUNSHARED) \ + $(PYTHON_FOR_BUILD) -m lib2to3.pgen2.driver $(DESTDIR)$(LIBDEST)/lib2to3/PatternGrammar.txt # Create the PLATDIR source directory, if one wasn't distributed.. $(srcdir)/Lib/$(PLATDIR): @@ -1340,7 +1342,7 @@ find . -name '*.so.[0-9]*.[0-9]*' -exec rm -f {} ';' find build -name 'fficonfig.h' -exec rm -f {} ';' || true find build -name 'fficonfig.py' -exec rm -f {} ';' || true - -rm -f $(srcdir)/Lib/lib2to3/*Grammar*.pickle + -rm -f Lib/lib2to3/*Grammar*.pickle -rm -f $(SYSCONFIGDATA) -rm -f Modules/_testembed Modules/_freeze_importlib diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -141,6 +141,9 @@ Tools/Demos ----------- +- Issue #15822: Really ensure 2to3 grammar pickles are properly installed + (replaces fixes for Issue #15645). + Documentation ------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:24 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:24 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_NEWS_entry_location=2E?= Message-ID: <3XF6K86K7PzQXB@mail.python.org> http://hg.python.org/cpython/rev/c5bc19ce4d2b changeset: 78914:c5bc19ce4d2b user: Georg Brandl date: Sun Sep 09 08:31:16 2012 +0200 summary: Fix NEWS entry location. files: Misc/NEWS | 9 ++++++--- 1 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -46,6 +46,12 @@ calling the C function wadd_wch()/mvwadd_wch() if the Python curses is linked to libncursesw. +Build +----- + +- Issue #15822: Really ensure 2to3 grammar pickles are properly installed + (replaces fixes for Issue #15645). + What's New in Python 3.3.0 Release Candidate 1? =============================================== @@ -141,9 +147,6 @@ Tools/Demos ----------- -- Issue #15822: Really ensure 2to3 grammar pickles are properly installed - (replaces fixes for Issue #15645). - Documentation ------------- -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:26 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:26 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Bump_to_3=2E3=2E0rc2=2E?= Message-ID: <3XF6KB2WPMzQWD@mail.python.org> http://hg.python.org/cpython/rev/1aa3fb9f761d changeset: 78915:1aa3fb9f761d user: Georg Brandl date: Sun Sep 09 08:56:46 2012 +0200 summary: Bump to 3.3.0rc2. files: Include/patchlevel.h | 4 ++-- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 2 +- Misc/RPM/python-3.3.spec | 2 +- README | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 3 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.3.0rc1+" +#define PY_VERSION "3.3.0rc2" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.3.0rc1" +__version__ = "3.3.0rc2" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.3.0rc1" +IDLE_VERSION = "3.3.0rc2" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -5,7 +5,7 @@ What's New in Python 3.3.0 Release Candidate 2? =============================================== -*Release date: XX-Sep-2012* +*Release date: 09-Sep-2012* Core and Builtins ----------------- diff --git a/Misc/RPM/python-3.3.spec b/Misc/RPM/python-3.3.spec --- a/Misc/RPM/python-3.3.spec +++ b/Misc/RPM/python-3.3.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.3.0rc1 +%define version 3.3.0rc2 %define libvers 3.3 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.3.0 release candidate 1 +This is Python version 3.3.0 release candidate 2 ================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:27 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:27 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315814=3A_Document?= =?utf-8?q?ation=3A_disallow_hashing_of_multi-dimensional_memoryviews=2E?= Message-ID: <3XF6KC6qMlzQYK@mail.python.org> http://hg.python.org/cpython/rev/71f4d80400f2 changeset: 78916:71f4d80400f2 user: Stefan Krah date: Sun Sep 02 14:50:56 2012 +0200 summary: Issue #15814: Documentation: disallow hashing of multi-dimensional memoryviews. files: Doc/library/stdtypes.rst | 14 ++++++++------ 1 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2376,8 +2376,9 @@ >>> data bytearray(b'z1spam') - Memoryviews of hashable (read-only) types with formats 'B', 'b' or 'c' - are also hashable. The hash is defined as ``hash(m) == hash(m.tobytes())``:: + One-dimensional memoryviews of hashable (read-only) types with formats + 'B', 'b' or 'c' are also hashable. The hash is defined as + ``hash(m) == hash(m.tobytes())``:: >>> v = memoryview(b'abcefg') >>> hash(v) == hash(b'abcefg') @@ -2388,12 +2389,13 @@ True .. versionchanged:: 3.3 - Memoryview objects with formats 'B', 'b' or 'c' are now hashable. + One-dimensional memoryviews with formats 'B', 'b' or 'c' are now hashable. .. note:: - Hashing of memoryviews with formats other than 'B', 'b' or 'c' is - possible in version 3.3.0, but will raise an error in 3.3.1 in order - to be compatible with the new memoryview equality definition. + Hashing of memoryviews with formats other than 'B', 'b' or 'c' as well + as hashing of multi-dimensional memoryviews is possible in version 3.3.0, + but will raise an error in 3.3.1 in order to be compatible with the new + memoryview equality definition. :class:`memoryview` has several methods: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:29 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:29 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315814=3A_Add_NEWS?= =?utf-8?q?_entry_regarding_intended_memoryview_hashing_restrictions?= Message-ID: <3XF6KF2xLzzQWD@mail.python.org> http://hg.python.org/cpython/rev/3ffd6ad93fe4 changeset: 78917:3ffd6ad93fe4 user: Nick Coghlan date: Mon Sep 03 21:46:33 2012 +1000 summary: Issue #15814: Add NEWS entry regarding intended memoryview hashing restrictions files: Misc/NEWS | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -52,6 +52,14 @@ - Issue #15822: Really ensure 2to3 grammar pickles are properly installed (replaces fixes for Issue #15645). +Documentation +------------- + +- Issue #15814: The memoryview enhancements in 3.3.0 accidentally permitted + the hashing of multi-dimensional memorviews and memoryviews with multi-byte + item formats. The intended restrictions have now been documented - they + will be correctly enforced in 3.3.1 + What's New in Python 3.3.0 Release Candidate 1? =============================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:30 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:30 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315814=3A_Update_w?= =?utf-8?q?hatsnew_to_the_current_state_of_hashing_memoryviews=2E?= Message-ID: <3XF6KG60yTzQXB@mail.python.org> http://hg.python.org/cpython/rev/88a0792e8ba3 changeset: 78918:88a0792e8ba3 tag: v3.3.0rc2 user: Stefan Krah date: Sat Sep 08 15:35:01 2012 +0200 summary: Issue #15814: Update whatsnew to the current state of hashing memoryviews. files: Doc/whatsnew/3.3.rst | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst --- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -158,9 +158,8 @@ * Multi-dimensional comparisons are supported for any array type. -* All array types are hashable if the exporting object is hashable - and the view is read-only. (Contributed by Antoine Pitrou in - :issue:`13411`) +* One-dimensional memoryviews of hashable (read-only) types with formats B, + b or c are now hashable. (Contributed by Antoine Pitrou in :issue:`13411`) * Arbitrary slicing of any 1-D arrays type is supported. For example, it is now possible to reverse a memoryview in O(1) by using a negative step. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:32 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:32 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Added_tag_v3=2E3=2E0rc2_fo?= =?utf-8?q?r_changeset_88a0792e8ba3?= Message-ID: <3XF6KJ1yV5zQQF@mail.python.org> http://hg.python.org/cpython/rev/91d15845e472 changeset: 78919:91d15845e472 user: Georg Brandl date: Sun Sep 09 09:04:21 2012 +0200 summary: Added tag v3.3.0rc2 for changeset 88a0792e8ba3 files: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -106,3 +106,4 @@ e15c554cd43eb23bc0a528a4e8741da9bbec9607 v3.3.0b1 4972a8f1b2aa3d7cdd64dc96aa7fa112fe1ea343 v3.3.0b2 8bb5c7bc46ba43804480f3e328e1fa956672c885 v3.3.0rc1 +88a0792e8ba3e4916b24c7e7a522c277d326d66e v3.3.0rc2 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:33 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:33 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Post-release_updates_for_3?= =?utf-8?b?LjMuMHJjMi4=?= Message-ID: <3XF6KK57RtzQXf@mail.python.org> http://hg.python.org/cpython/rev/72598063c6c4 changeset: 78920:72598063c6c4 user: Georg Brandl date: Sun Sep 09 11:16:41 2012 +0200 summary: Post-release updates for 3.3.0rc2. files: Include/patchlevel.h | 2 +- Misc/NEWS | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletions(-) diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -23,7 +23,7 @@ #define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.3.0rc2" +#define PY_VERSION "3.3.0rc2+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,18 @@ Python News +++++++++++ +What's New in Python 3.3.0? +=========================== + +*Release date: XX-Sep-2012* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.3.0 Release Candidate 2? =============================================== -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 11:19:35 2012 From: python-checkins at python.org (georg.brandl) Date: Sun, 9 Sep 2012 11:19:35 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge_in_changes_from_3=2E3=2E0rc2_release_clone=2E?= Message-ID: <3XF6KM2z5ZzQWZ@mail.python.org> http://hg.python.org/cpython/rev/800507fb0a7e changeset: 78921:800507fb0a7e parent: 78897:a829889f96b0 parent: 78920:72598063c6c4 user: Georg Brandl date: Sun Sep 09 11:19:17 2012 +0200 summary: Merge in changes from 3.3.0rc2 release clone. files: .hgtags | 1 + Include/patchlevel.h | 4 +- Lib/distutils/__init__.py | 2 +- Lib/idlelib/idlever.py | 2 +- Misc/NEWS | 40 +++++++++++++++++++------- Misc/RPM/python-3.3.spec | 2 +- README | 2 +- 7 files changed, 36 insertions(+), 17 deletions(-) diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -106,3 +106,4 @@ e15c554cd43eb23bc0a528a4e8741da9bbec9607 v3.3.0b1 4972a8f1b2aa3d7cdd64dc96aa7fa112fe1ea343 v3.3.0b2 8bb5c7bc46ba43804480f3e328e1fa956672c885 v3.3.0rc1 +88a0792e8ba3e4916b24c7e7a522c277d326d66e v3.3.0rc2 diff --git a/Include/patchlevel.h b/Include/patchlevel.h --- a/Include/patchlevel.h +++ b/Include/patchlevel.h @@ -20,10 +20,10 @@ #define PY_MINOR_VERSION 3 #define PY_MICRO_VERSION 0 #define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_GAMMA -#define PY_RELEASE_SERIAL 1 +#define PY_RELEASE_SERIAL 2 /* Version as a string */ -#define PY_VERSION "3.3.0rc1+" +#define PY_VERSION "3.3.0rc2+" /*--end constants--*/ /* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2. diff --git a/Lib/distutils/__init__.py b/Lib/distutils/__init__.py --- a/Lib/distutils/__init__.py +++ b/Lib/distutils/__init__.py @@ -13,5 +13,5 @@ # Updated automatically by the Python release process. # #--start constants-- -__version__ = "3.3.0rc1" +__version__ = "3.3.0rc2" #--end constants-- diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py --- a/Lib/idlelib/idlever.py +++ b/Lib/idlelib/idlever.py @@ -1,1 +1,1 @@ -IDLE_VERSION = "3.3.0rc1" +IDLE_VERSION = "3.3.0rc2" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,11 +10,6 @@ Core and Builtins ----------------- -- Issue #13992: The trashcan mechanism is now thread-safe. This eliminates - sporadic crashes in multi-thread programs when several long deallocator - chains ran concurrently and involved subclasses of built-in container - types. - - Issue #15839: Convert SystemErrors in super() to RuntimeErrors. - Issue #15846: Fix SystemError which happened when using ast.parse in an @@ -62,9 +57,6 @@ - Issue #15819: Make sure we can build Python out-of-tree from a readonly source directory. (Somewhat related to Issue #9860.) -- Issue #15822: Really ensure 2to3 grammar pickles are properly installed - (replaces fixes for Issue #15645). - Documentation ------------- @@ -75,14 +67,31 @@ ----------- +What's New in Python 3.3.0? +=========================== + +*Release date: XX-Sep-2012* + +Core and Builtins +----------------- + +Library +------- + + What's New in Python 3.3.0 Release Candidate 2? =============================================== -*Release date: XX-Sep-2012* +*Release date: 09-Sep-2012* Core and Builtins ----------------- +- Issue #13992: The trashcan mechanism is now thread-safe. This eliminates + sporadic crashes in multi-thread programs when several long deallocator + chains ran concurrently and involved subclasses of built-in container + types. + - Issue #15784: Modify OSError.__str__() to better distinguish between errno error numbers and Windows error numbers. @@ -91,11 +100,14 @@ Library ------- +- Issue #15847: Fix a regression in argparse, which did not accept tuples + as argument lists anymore. + +- Issue #15828: Restore support for C extensions in imp.load_module(). + - Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. -- Issue #15828: Restore support for C extensions in imp.load_module() - - Issue #10650: Deprecate the watchexp parameter of the Decimal.quantize() method. @@ -111,6 +123,12 @@ calling the C function wadd_wch()/mvwadd_wch() if the Python curses is linked to libncursesw. +Build +----- + +- Issue #15822: Really ensure 2to3 grammar pickles are properly installed + (replaces fixes for Issue #15645). + Documentation ------------- diff --git a/Misc/RPM/python-3.3.spec b/Misc/RPM/python-3.3.spec --- a/Misc/RPM/python-3.3.spec +++ b/Misc/RPM/python-3.3.spec @@ -39,7 +39,7 @@ %define name python #--start constants-- -%define version 3.3.0rc1 +%define version 3.3.0rc2 %define libvers 3.3 #--end constants-- %define release 1pydotorg diff --git a/README b/README --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Python version 3.3.0 release candidate 1 +This is Python version 3.3.0 release candidate 2 ================================================ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 19:28:07 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 9 Sep 2012 19:28:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1ODgx?= =?utf-8?q?=3A_Fixed_atexit_hook_in_multiprocessing=2E?= Message-ID: <3XFK934lnczQW8@mail.python.org> http://hg.python.org/cpython/rev/27d410dd5431 changeset: 78922:27d410dd5431 branch: 3.2 parent: 78895:adc5e6aca251 user: Alexander Belopolsky date: Sun Sep 09 13:16:15 2012 -0400 summary: Issue #15881: Fixed atexit hook in multiprocessing. files: Doc/ACKS.txt | 1 + Lib/multiprocessing/util.py | 50 ++++++++++++++++++------- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt --- a/Doc/ACKS.txt +++ b/Doc/ACKS.txt @@ -236,3 +236,4 @@ * Moshe Zadka * Milan Zamazal * Cheng Zhang + * Chris McDonough diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -247,6 +247,12 @@ Finalizers with highest priority are called first; finalizers with the same priority will be called in reverse order of creation. ''' + if _finalizer_registry is None: + # This function may be called after this module's globals are + # destroyed. See the _exit_function function in this module for more + # notes. + return + if minpriority is None: f = lambda p : p[0][0] is not None else: @@ -278,24 +284,40 @@ _exiting = False -def _exit_function(): +def _exit_function(info=info, debug=debug, _run_finalizers=_run_finalizers, + active_children=active_children, + current_process=current_process): + # We hold on to references to functions in the arglist due to the + # situation described below, where this function is called after this + # module's globals are destroyed. + global _exiting - info('process shutting down') - debug('running all "atexit" finalizers with priority >= 0') - _run_finalizers(0) + if not _exiting: + info('process shutting down') + debug('running all "atexit" finalizers with priority >= 0') + _run_finalizers(0) + if current_process() is not None: + # We check if the current process is None here because if + # it's None, any call to ``active_children()`` will throw an + # AttributeError (active_children winds up trying to get + # attributes from util._current_process). This happens in a + # variety of shutdown circumstances that are not well-understood + # because module-scope variables are not apparently supposed to + # be destroyed until after this function is called. However, + # they are indeed destroyed before this function is called. See + # issues #9775 and #15881. Also related: #4106, #9205, and #9207. + for p in active_children(): + if p._daemonic: + info('calling terminate() for daemon %s', p.name) + p._popen.terminate() - for p in active_children(): - if p._daemonic: - info('calling terminate() for daemon %s', p.name) - p._popen.terminate() + for p in active_children(): + info('calling join() for process %s', p.name) + p.join() - for p in active_children(): - info('calling join() for process %s', p.name) - p.join() - - debug('running the remaining "atexit" finalizers') - _run_finalizers() + debug('running the remaining "atexit" finalizers') + _run_finalizers() atexit.register(_exit_function) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 19:28:10 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 9 Sep 2012 19:28:10 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315881=3A_Fixed_at?= =?utf-8?q?exit_hook_in_multiprocessing=2E?= Message-ID: <3XFK960MNrzQZC@mail.python.org> http://hg.python.org/cpython/rev/08c680918ff8 changeset: 78923:08c680918ff8 parent: 78921:800507fb0a7e user: Alexander Belopolsky date: Sun Sep 09 13:20:58 2012 -0400 summary: Issue #15881: Fixed atexit hook in multiprocessing. files: Doc/ACKS.txt | 1 + Lib/multiprocessing/util.py | 39 +++++++++++++++++++----- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt --- a/Doc/ACKS.txt +++ b/Doc/ACKS.txt @@ -238,3 +238,4 @@ * Moshe Zadka * Milan Zamazal * Cheng Zhang + * Chris McDonough diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -235,6 +235,12 @@ Finalizers with highest priority are called first; finalizers with the same priority will be called in reverse order of creation. ''' + if _finalizer_registry is None: + # This function may be called after this module's globals are + # destroyed. See the _exit_function function in this module for more + # notes. + return + if minpriority is None: f = lambda p : p[0][0] is not None else: @@ -266,7 +272,13 @@ _exiting = False -def _exit_function(): +def _exit_function(info=info, debug=debug, _run_finalizers=_run_finalizers, + active_children=active_children, + current_process=current_process): + # We hold on to references to functions in the arglist due to the + # situation described below, where this function is called after this + # module's globals are destroyed. + global _exiting if not _exiting: @@ -276,14 +288,25 @@ debug('running all "atexit" finalizers with priority >= 0') _run_finalizers(0) - for p in active_children(): - if p._daemonic: - info('calling terminate() for daemon %s', p.name) - p._popen.terminate() + if current_process() is not None: + # We check if the current process is None here because if + # it's None, any call to ``active_children()`` will throw an + # AttributeError (active_children winds up trying to get + # attributes from util._current_process). This happens in a + # variety of shutdown circumstances that are not well-understood + # because module-scope variables are not apparently supposed to + # be destroyed until after this function is called. However, + # they are indeed destroyed before this function is called. See + # issues #9775 and #15881. Also related: #4106, #9205, and #9207. - for p in active_children(): - info('calling join() for process %s', p.name) - p.join() + for p in active_children(): + if p._daemonic: + info('calling terminate() for daemon %s', p.name) + p._popen.terminate() + + for p in active_children(): + info('calling join() for process %s', p.name) + p.join() debug('running the remaining "atexit" finalizers') _run_finalizers() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 19:28:11 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 9 Sep 2012 19:28:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fixed_whitespa?= =?utf-8?q?ce?= Message-ID: <3XFK973Vp4zQYq@mail.python.org> http://hg.python.org/cpython/rev/89a5169f2979 changeset: 78924:89a5169f2979 branch: 3.2 parent: 78922:27d410dd5431 user: Alexander Belopolsky date: Sun Sep 09 13:22:45 2012 -0400 summary: Fixed whitespace files: Lib/multiprocessing/util.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -252,7 +252,7 @@ # destroyed. See the _exit_function function in this module for more # notes. return - + if minpriority is None: f = lambda p : p[0][0] is not None else: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 19:28:13 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 9 Sep 2012 19:28:13 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_whitespace?= Message-ID: <3XFK9937YlzQZt@mail.python.org> http://hg.python.org/cpython/rev/6c4dc8f7e3e3 changeset: 78925:6c4dc8f7e3e3 parent: 78923:08c680918ff8 user: Alexander Belopolsky date: Sun Sep 09 13:25:06 2012 -0400 summary: Fixed whitespace files: Lib/multiprocessing/util.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -240,7 +240,7 @@ # destroyed. See the _exit_function function in this module for more # notes. return - + if minpriority is None: f = lambda p : p[0][0] is not None else: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 19:31:21 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 9 Sep 2012 19:31:21 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1ODgx?= =?utf-8?q?=3A_Fixed_3=2E2_backport=2E?= Message-ID: <3XFKDn6btCzQZ5@mail.python.org> http://hg.python.org/cpython/rev/db67b848ddc3 changeset: 78926:db67b848ddc3 branch: 3.2 parent: 78924:89a5169f2979 user: Alexander Belopolsky date: Sun Sep 09 13:31:08 2012 -0400 summary: Issue #15881: Fixed 3.2 backport. files: Lib/multiprocessing/util.py | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -294,6 +294,8 @@ global _exiting if not _exiting: + _exiting = True + info('process shutting down') debug('running all "atexit" finalizers with priority >= 0') _run_finalizers(0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Sep 9 20:12:02 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Sun, 9 Sep 2012 20:12:02 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1ODgx?= =?utf-8?q?=3A_Added_NEWS_entry_and_proper_credit=2E?= Message-ID: <3XFL7k0m6bzQTf@mail.python.org> http://hg.python.org/cpython/rev/b05547e8ff92 changeset: 78927:b05547e8ff92 branch: 3.2 user: Alexander Belopolsky date: Sun Sep 09 14:11:45 2012 -0400 summary: Issue #15881: Added NEWS entry and proper credit. files: Doc/ACKS.txt | 1 - Misc/NEWS | 3 +++ 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt --- a/Doc/ACKS.txt +++ b/Doc/ACKS.txt @@ -236,4 +236,3 @@ * Moshe Zadka * Milan Zamazal * Cheng Zhang - * Chris McDonough diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -120,6 +120,9 @@ Library ------- +- Issue #15881: Fixed atexit hook in multiprocessing. Original patch + by Chris McDonough. + - Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. -- Repository URL: http://hg.python.org/cpython From brett at python.org Sun Sep 9 20:56:57 2012 From: brett at python.org (Brett Cannon) Date: Sun, 9 Sep 2012 14:56:57 -0400 Subject: [Python-checkins] devguide: Update committers list location. In-Reply-To: <3XF3gB6HtHzQNv@mail.python.org> References: <3XF3gB6HtHzQNv@mail.python.org> Message-ID: Did you mean to use http://docs.python.org/devguide/developers.html instead of http://hg.python.org/committers.txt as the former lists why while the latter just lists usernames? On Sun, Sep 9, 2012 at 3:19 AM, georg.brandl wrote: > http://hg.python.org/devguide/rev/b40bfc99c54f > changeset: 548:b40bfc99c54f > user: Georg Brandl > date: Sun Sep 09 09:20:23 2012 +0200 > summary: > Update committers list location. > > files: > coredev.rst | 4 ++-- > faq.rst | 2 +- > 2 files changed, 3 insertions(+), 3 deletions(-) > > > diff --git a/coredev.rst b/coredev.rst > --- a/coredev.rst > +++ b/coredev.rst > @@ -25,7 +25,7 @@ > able to commit them without supervision. > > A complete list of core developer usernames can be found at > -http://www.python.org/dev/committers. :ref:`developers` lists when and > why > +http://hg.python.org/committers.txt. :ref:`developers` lists when and why > someone received commit privileges. > > > @@ -68,7 +68,7 @@ > This should match your username on the issue tracker. > > You can verify your commit access by looking at > -http://www.python.org/dev/committers which lists all core developers by > +http://hg.python.org/committers.txt which lists all core developers by > username. If you want to practice, there is a `test repository > `_ where you can freely commit and push any > changes you like:: > diff --git a/faq.rst b/faq.rst > --- a/faq.rst > +++ b/faq.rst > @@ -96,7 +96,7 @@ > On the `issue tracker`_, most core developers will have the Python logo > appear next to their name. > > -.. _full list of developers: http://www.python.org/dev/committers > +.. _full list of developers: http://hg.python.org/committers.txt > > > What standards of behaviour are expected in these communication channels? > > -- > Repository URL: http://hg.python.org/devguide > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From g.brandl at gmx.net Sun Sep 9 21:45:41 2012 From: g.brandl at gmx.net (Georg Brandl) Date: Sun, 09 Sep 2012 21:45:41 +0200 Subject: [Python-checkins] devguide: Update committers list location. In-Reply-To: References: <3XF3gB6HtHzQNv@mail.python.org> Message-ID: No, I just updated the location. Georg On 09.09.2012 20:56, Brett Cannon wrote: > Did you mean to use http://docs.python.org/devguide/developers.html instead > of http://hg.python.org/committers.txt as the former lists why while the latter > just lists usernames? > > On Sun, Sep 9, 2012 at 3:19 AM, georg.brandl > wrote: > > http://hg.python.org/devguide/rev/b40bfc99c54f > changeset: 548:b40bfc99c54f > user: Georg Brandl > > date: Sun Sep 09 09:20:23 2012 +0200 > summary: > Update committers list location. > > files: > coredev.rst | 4 ++-- > faq.rst | 2 +- > 2 files changed, 3 insertions(+), 3 deletions(-) > > > diff --git a/coredev.rst b/coredev.rst > --- a/coredev.rst > +++ b/coredev.rst > @@ -25,7 +25,7 @@ > able to commit them without supervision. > > A complete list of core developer usernames can be found at > -http://www.python.org/dev/committers. :ref:`developers` lists when and why > +http://hg.python.org/committers.txt. :ref:`developers` lists when and why > someone received commit privileges. > > > @@ -68,7 +68,7 @@ > This should match your username on the issue tracker. > > You can verify your commit access by looking at > -http://www.python.org/dev/committers which lists all core developers by > +http://hg.python.org/committers.txt which lists all core developers by > username. If you want to practice, there is a `test repository > `_ where you can freely commit and push any > changes you like:: > diff --git a/faq.rst b/faq.rst > --- a/faq.rst > +++ b/faq.rst > @@ -96,7 +96,7 @@ > On the `issue tracker`_, most core developers will have the Python logo > appear next to their name. > > -.. _full list of developers: http://www.python.org/dev/committers > +.. _full list of developers: http://hg.python.org/committers.txt > > > What standards of behaviour are expected in these communication channels? > > -- > Repository URL: http://hg.python.org/devguide > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > > > > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From python-checkins at python.org Mon Sep 10 01:01:30 2012 From: python-checkins at python.org (alexander.belopolsky) Date: Mon, 10 Sep 2012 01:01:30 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_merge?= Message-ID: <3XFSYk1xG8zQbJ@mail.python.org> http://hg.python.org/cpython/rev/1ffc26c5122c changeset: 78928:1ffc26c5122c parent: 78925:6c4dc8f7e3e3 parent: 78927:b05547e8ff92 user: Alexander Belopolsky date: Sun Sep 09 19:01:20 2012 -0400 summary: merge files: Misc/NEWS | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,8 +21,15 @@ Library ------- + - Issue #15876: Fix a refleak in the curses module: window.encoding. +- Issue #15881: Fixed atexit hook in multiprocessing. Original patch + by Chris McDonough. + +- Issue #15340: Fix importing the random module when /dev/urandom cannot + be opened. This was a regression caused by the hash randomization patch. + - Issue #15841: The readable(), writable() and seekable() methods of BytesIO and StringIO objects now raise ValueError when the object has been closed. Patch by Alessandro Moura. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 01:24:45 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 01:24:45 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogQ2xvc2VzICMxNTY3?= =?utf-8?q?6=3A_mmap=3A_add_empty_file_check_prior_to_offset_check?= Message-ID: <3XFT4Y08nDzQZJ@mail.python.org> http://hg.python.org/cpython/rev/d85f80b31b54 changeset: 78929:d85f80b31b54 branch: 3.2 parent: 78927:b05547e8ff92 user: Jesus Cea date: Mon Sep 10 00:27:55 2012 +0200 summary: Closes #15676: mmap: add empty file check prior to offset check files: Lib/test/test_mmap.py | 9 +++++++++ Misc/NEWS | 3 +++ Modules/mmapmodule.c | 5 +++++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -459,6 +459,15 @@ f.flush () return mmap.mmap (f.fileno(), 0) + def test_empty_file (self): + f = open (TESTFN, 'w+b') + f.close() + f = open(TESTFN, "rb") + self.assertRaisesRegex(ValueError, + "cannot mmap an empty file", + mmap.mmap, f.fileno(), 0, access=mmap.ACCESS_READ) + f.close() + def test_offset (self): f = open (TESTFN, 'w+b') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -463,6 +463,9 @@ Extension Modules ----------------- +- Issue #15676: Now "mmap" check for empty files before doing the + offset check. Patch by Steven Willis. + - Issue #6493: An issue in ctypes on Windows that caused structure bitfields of type ctypes.c_uint32 and width 32 to incorrectly be set has been fixed. diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1141,6 +1141,11 @@ if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { if (map_size == 0) { off_t calc_size; + if (st.st_size == 0) { + PyErr_SetString(PyExc_ValueError, + "cannot mmap an empty file"); + return NULL; + } if (offset >= st.st_size) { PyErr_SetString(PyExc_ValueError, "mmap offset is greater than file size"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 01:24:46 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 01:24:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Closes_=2315676=3A_mmap=3A_add_empty_file_check_prior_to?= =?utf-8?q?_offset_check?= Message-ID: <3XFT4Z52s4zQbL@mail.python.org> http://hg.python.org/cpython/rev/f962ec8e47a1 changeset: 78930:f962ec8e47a1 parent: 78928:1ffc26c5122c parent: 78929:d85f80b31b54 user: Jesus Cea date: Mon Sep 10 01:23:05 2012 +0200 summary: Closes #15676: mmap: add empty file check prior to offset check files: Lib/test/test_mmap.py | 9 +++++++++ Misc/NEWS | 3 +++ Modules/mmapmodule.c | 5 +++++ 3 files changed, 17 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -488,6 +488,15 @@ f.flush () return mmap.mmap (f.fileno(), 0) + def test_empty_file (self): + f = open (TESTFN, 'w+b') + f.close() + f = open(TESTFN, "rb") + self.assertRaisesRegex(ValueError, + "cannot mmap an empty file", + mmap.mmap, f.fileno(), 0, access=mmap.ACCESS_READ) + f.close() + def test_offset (self): f = open (TESTFN, 'w+b') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -544,6 +544,9 @@ Extension Modules ----------------- +- Issue #15676: Now "mmap" check for empty files before doing the + offset check. Patch by Steven Willis. + - Issue #6493: An issue in ctypes on Windows that caused structure bitfields of type ctypes.c_uint32 and width 32 to incorrectly be set has been fixed. diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1163,6 +1163,11 @@ if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { if (map_size == 0) { off_t calc_size; + if (st.st_size == 0) { + PyErr_SetString(PyExc_ValueError, + "cannot mmap an empty file"); + return NULL; + } if (offset >= st.st_size) { PyErr_SetString(PyExc_ValueError, "mmap offset is greater than file size"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 01:24:48 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 01:24:48 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogQ2xvc2VzICMxNTY3?= =?utf-8?q?6=3A_mmap=3A_add_empty_file_check_prior_to_offset_check?= Message-ID: <3XFT4c1kS9zQbT@mail.python.org> http://hg.python.org/cpython/rev/27837a33790d changeset: 78931:27837a33790d branch: 2.7 parent: 78894:2def9ef683da user: Jesus Cea date: Mon Sep 10 00:22:39 2012 +0200 summary: Closes #15676: mmap: add empty file check prior to offset check files: Lib/test/test_mmap.py | 16 ++++++++++++++++ Misc/NEWS | 3 +++ Modules/mmapmodule.c | 5 +++++ 3 files changed, 24 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -466,6 +466,22 @@ f.flush () return mmap.mmap (f.fileno(), 0) + def test_empty_file (self): + f = open (TESTFN, 'w+b') + f.close() + f = open(TESTFN, "rb") + try: + m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + m.close() + f.close() + self.fail("should not have been able to mmap empty file") + except ValueError as e: + f.close() + self.assertEqual(e.message, "cannot mmap an empty file") + except: + f.close() + self.fail("unexpected exception: " + str(e)) + def test_offset (self): f = open (TESTFN, 'w+b') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -103,6 +103,9 @@ Library ------- +- Issue #15676: Now "mmap" check for empty files before doing the + offset check. Patch by Steven Willis. + - Issue #15340: Fix importing the random module when /dev/urandom cannot be opened. This was a regression caused by the hash randomization patch. diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1189,6 +1189,11 @@ if (fd != -1 && fstat(fd, &st) == 0 && S_ISREG(st.st_mode)) { if (map_size == 0) { off_t calc_size; + if (st.st_size == 0) { + PyErr_SetString(PyExc_ValueError, + "cannot mmap an empty file"); + return NULL; + } if (offset >= st.st_size) { PyErr_SetString(PyExc_ValueError, "mmap offset is greater than file size"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 01:25:59 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 01:25:59 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Make_sure_that_*really*_no?= =?utf-8?q?_more_than_sizeof=28ifr=2Eifr=5Fname=29_chars_are_strcpy-ed?= Message-ID: <3XFT5z6kCCzQZJ@mail.python.org> http://hg.python.org/cpython/rev/80909b23ca1e changeset: 78932:80909b23ca1e parent: 78930:f962ec8e47a1 user: Christian Heimes date: Mon Sep 10 01:25:50 2012 +0200 summary: Make sure that *really* no more than sizeof(ifr.ifr_name) chars are strcpy-ed to ifr.ifr_name and that the string is *always* NUL terminated. New code shouldn't use strcpy(), too. CID 719692 files: Modules/socketmodule.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -1674,7 +1674,8 @@ if (len == 0) { ifr.ifr_ifindex = 0; } else if (len < sizeof(ifr.ifr_name)) { - strcpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName)); + strncpy(ifr.ifr_name, PyBytes_AS_STRING(interfaceName), sizeof(ifr.ifr_name)); + ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0'; if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr) < 0) { s->errorhandler(); Py_DECREF(interfaceName); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 02:00:43 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 02:00:43 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_two_memory_leaks_in_?= =?utf-8?q?make=5Ffilename=28=29_in_zipimport=2Ec=2E_The_allocated_buffer?= Message-ID: <3XFTt36v81zQTR@mail.python.org> http://hg.python.org/cpython/rev/6bd9626b0cc6 changeset: 78933:6bd9626b0cc6 user: Christian Heimes date: Mon Sep 10 02:00:34 2012 +0200 summary: Fixed two memory leaks in make_filename() in zipimport.c. The allocated buffer wasn't cleaned up in two error cases. CID 486832 files: Modules/zipimport.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Modules/zipimport.c b/Modules/zipimport.c --- a/Modules/zipimport.c +++ b/Modules/zipimport.c @@ -236,12 +236,16 @@ return NULL; } - if (!PyUnicode_AsUCS4(prefix, p, len, 0)) + if (!PyUnicode_AsUCS4(prefix, p, len, 0)) { + PyMem_Free(buf); return NULL; + } p += PyUnicode_GET_LENGTH(prefix); len -= PyUnicode_GET_LENGTH(prefix); - if (!PyUnicode_AsUCS4(name, p, len, 1)) + if (!PyUnicode_AsUCS4(name, p, len, 1)) { + PyMem_Free(buf); return NULL; + } for (; *p; p++) { if (*p == '.') *p = SEP; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 02:46:20 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 02:46:20 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogUHlfVFlQRSgpIGhh?= =?utf-8?q?s_already_dereferenced_self_before_the_NULL_check=2E_Moved_Py?= =?utf-8?b?X1RZUEUoKQ==?= Message-ID: <3XFVth3ysyzQZZ@mail.python.org> http://hg.python.org/cpython/rev/dcddbd41f08b changeset: 78934:dcddbd41f08b branch: 3.2 parent: 78929:d85f80b31b54 user: Christian Heimes date: Mon Sep 10 02:45:31 2012 +0200 summary: Py_TYPE() has already dereferenced self before the NULL check. Moved Py_TYPE() after the check for self == NULL files: Objects/classobject.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Objects/classobject.c b/Objects/classobject.c --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -218,7 +218,7 @@ { PyObject *self = a->im_self; PyObject *func = a->im_func; - PyObject *klass = (PyObject*)Py_TYPE(self); + PyObject *klass; PyObject *funcname = NULL ,*klassname = NULL, *result = NULL; char *defname = "?"; @@ -226,6 +226,7 @@ PyErr_BadInternalCall(); return NULL; } + klass = (PyObject*)Py_TYPE(self); funcname = PyObject_GetAttrString(func, "__name__"); if (funcname == NULL) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 02:46:22 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 02:46:22 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Py=5FTYPE=28=29_has_already_dereferenced_self_before_the?= =?utf-8?q?_NULL_check=2E_Moved_Py=5FTYPE=28=29?= Message-ID: <3XFVtk1jHjzQbT@mail.python.org> http://hg.python.org/cpython/rev/39e3f06cf6f0 changeset: 78935:39e3f06cf6f0 parent: 78933:6bd9626b0cc6 parent: 78934:dcddbd41f08b user: Christian Heimes date: Mon Sep 10 02:45:56 2012 +0200 summary: Py_TYPE() has already dereferenced self before the NULL check. Moved Py_TYPE() after the check for self == NULL files: Objects/classobject.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Objects/classobject.c b/Objects/classobject.c --- a/Objects/classobject.c +++ b/Objects/classobject.c @@ -219,7 +219,7 @@ { PyObject *self = a->im_self; PyObject *func = a->im_func; - PyObject *klass = (PyObject*)Py_TYPE(self); + PyObject *klass; PyObject *funcname = NULL ,*klassname = NULL, *result = NULL; char *defname = "?"; @@ -227,6 +227,7 @@ PyErr_BadInternalCall(); return NULL; } + klass = (PyObject*)Py_TYPE(self); funcname = _PyObject_GetAttrId(func, &PyId___name__); if (funcname == NULL) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 02:51:45 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 02:51:45 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_resource_leak_to_scr?= =?utf-8?q?atch_when_=5FPyUnicodeWriter=5FPrepare_fails?= Message-ID: <3XFW0x0d9NzQbP@mail.python.org> http://hg.python.org/cpython/rev/1349e9537f91 changeset: 78936:1349e9537f91 user: Christian Heimes date: Mon Sep 10 02:51:27 2012 +0200 summary: Fixed resource leak to scratch when _PyUnicodeWriter_Prepare fails files: Objects/longobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -1628,8 +1628,10 @@ strlen++; } if (writer) { - if (_PyUnicodeWriter_Prepare(writer, strlen, '9') == -1) + if (_PyUnicodeWriter_Prepare(writer, strlen, '9') == -1) { + Py_DECREF(scratch); return -1; + } kind = writer->kind; str = NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 02:55:48 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 02:55:48 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogUHlUdXBsZV9QYWNr?= =?utf-8?q?=28=29_was_missing_va=5Fend=28=29_in_its_error_branch_which_lea?= =?utf-8?q?d_to_a?= Message-ID: <3XFW5c4RqmzQTX@mail.python.org> http://hg.python.org/cpython/rev/bbc580e004d7 changeset: 78937:bbc580e004d7 branch: 3.2 parent: 78934:dcddbd41f08b user: Christian Heimes date: Mon Sep 10 02:54:51 2012 +0200 summary: PyTuple_Pack() was missing va_end() in its error branch which lead to a resource leak. files: Objects/tupleobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -194,8 +194,10 @@ va_start(vargs, n); result = PyTuple_New(n); - if (result == NULL) + if (result == NULL) { + va_end(vargs); return NULL; + } items = ((PyTupleObject *)result)->ob_item; for (i = 0; i < n; i++) { o = va_arg(vargs, PyObject *); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 02:55:50 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 02:55:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_PyTuple=5FPack=28=29_was_missing_va=5Fend=28=29_in_its_e?= =?utf-8?q?rror_branch_which_lead_to_a?= Message-ID: <3XFW5f1k7BzQTX@mail.python.org> http://hg.python.org/cpython/rev/033b409f7cd6 changeset: 78938:033b409f7cd6 parent: 78936:1349e9537f91 parent: 78937:bbc580e004d7 user: Christian Heimes date: Mon Sep 10 02:55:13 2012 +0200 summary: PyTuple_Pack() was missing va_end() in its error branch which lead to a resource leak. files: Objects/tupleobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -210,8 +210,10 @@ va_start(vargs, n); result = PyTuple_New(n); - if (result == NULL) + if (result == NULL) { + va_end(vargs); return NULL; + } items = ((PyTupleObject *)result)->ob_item; for (i = 0; i < n; i++) { o = va_arg(vargs, PyObject *); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 02:55:51 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 02:55:51 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogUHlUdXBsZV9QYWNr?= =?utf-8?q?=28=29_was_missing_va=5Fend=28=29_in_its_error_branch_which_lea?= =?utf-8?q?d_to_a?= Message-ID: <3XFW5g4xw2zQbp@mail.python.org> http://hg.python.org/cpython/rev/bb0390c1d3d4 changeset: 78939:bb0390c1d3d4 branch: 2.7 parent: 78931:27837a33790d user: Christian Heimes date: Mon Sep 10 02:54:51 2012 +0200 summary: PyTuple_Pack() was missing va_end() in its error branch which lead to a resource leak. files: Objects/tupleobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -192,8 +192,10 @@ va_start(vargs, n); result = PyTuple_New(n); - if (result == NULL) + if (result == NULL) { + va_end(vargs); return NULL; + } items = ((PyTupleObject *)result)->ob_item; for (i = 0; i < n; i++) { o = va_arg(vargs, PyObject *); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 03:02:04 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 03:02:04 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fixed_possible?= =?utf-8?q?_reference_leak_to_mod_when_type=5Fname=28=29_returns_NULL?= Message-ID: <3XFWDr4JLBzQTX@mail.python.org> http://hg.python.org/cpython/rev/9f4e6c0c18e6 changeset: 78940:9f4e6c0c18e6 branch: 3.2 parent: 78937:bbc580e004d7 user: Christian Heimes date: Mon Sep 10 03:00:14 2012 +0200 summary: Fixed possible reference leak to mod when type_name() returns NULL files: Objects/typeobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -647,8 +647,10 @@ mod = NULL; } name = type_name(type, NULL); - if (name == NULL) + if (name == NULL) { + Py_XDECREF(mod); return NULL; + } if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins")) rtn = PyUnicode_FromFormat("", mod, name); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 03:02:06 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 03:02:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Fixed_possible_reference_leak_to_mod_when_type=5Fname=28?= =?utf-8?q?=29_returns_NULL?= Message-ID: <3XFWDt1MJ2zQTX@mail.python.org> http://hg.python.org/cpython/rev/517aa5576ae3 changeset: 78941:517aa5576ae3 parent: 78938:033b409f7cd6 parent: 78940:9f4e6c0c18e6 user: Christian Heimes date: Mon Sep 10 03:01:16 2012 +0200 summary: Fixed possible reference leak to mod when type_name() returns NULL files: Objects/typeobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -691,8 +691,10 @@ mod = NULL; } name = type_qualname(type, NULL); - if (name == NULL) + if (name == NULL) { + Py_XDECREF(mod); return NULL; + } if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins")) rtn = PyUnicode_FromFormat("", mod, name); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 03:02:07 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 03:02:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fixed_possible?= =?utf-8?q?_reference_leak_to_mod_when_type=5Fname=28=29_returns_NULL?= Message-ID: <3XFWDv4CqrzQbd@mail.python.org> http://hg.python.org/cpython/rev/2b611280ff36 changeset: 78942:2b611280ff36 branch: 2.7 parent: 78939:bb0390c1d3d4 user: Christian Heimes date: Mon Sep 10 03:00:14 2012 +0200 summary: Fixed possible reference leak to mod when type_name() returns NULL files: Objects/typeobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -686,8 +686,10 @@ mod = NULL; } name = type_name(type, NULL); - if (name == NULL) + if (name == NULL) { + Py_XDECREF(mod); return NULL; + } if (type->tp_flags & Py_TPFLAGS_HEAPTYPE) kind = "class"; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 03:09:54 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 03:09:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Closed_referen?= =?utf-8?q?ce_leak_of_variable_=27k=27_in_function_ste=5Fnew_which_wasn=27?= =?utf-8?q?t_decrefed?= Message-ID: <3XFWPt4nn7zQbP@mail.python.org> http://hg.python.org/cpython/rev/ad3824a90261 changeset: 78943:ad3824a90261 branch: 3.2 parent: 78940:9f4e6c0c18e6 user: Christian Heimes date: Mon Sep 10 03:08:46 2012 +0200 summary: Closed reference leak of variable 'k' in function ste_new which wasn't decrefed in error cases files: Python/symtable.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -28,7 +28,7 @@ void *key, int lineno, int col_offset) { PySTEntryObject *ste = NULL; - PyObject *k; + PyObject *k = NULL; k = PyLong_FromVoidPtr(key); if (k == NULL) @@ -83,6 +83,7 @@ return ste; fail: + Py_XDECREF(k); Py_XDECREF(ste); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 03:09:56 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 03:09:56 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Closed_referen?= =?utf-8?q?ce_leak_of_variable_=27k=27_in_function_ste=5Fnew_which_wasn=27?= =?utf-8?q?t_decrefed?= Message-ID: <3XFWPw1RhMzQbk@mail.python.org> http://hg.python.org/cpython/rev/61446e56f683 changeset: 78944:61446e56f683 branch: 2.7 parent: 78942:2b611280ff36 user: Christian Heimes date: Mon Sep 10 03:08:46 2012 +0200 summary: Closed reference leak of variable 'k' in function ste_new which wasn't decrefed in error cases files: Python/symtable.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -22,7 +22,7 @@ void *key, int lineno) { PySTEntryObject *ste = NULL; - PyObject *k; + PyObject *k = NULL; k = PyLong_FromVoidPtr(key); if (k == NULL) @@ -75,6 +75,7 @@ return ste; fail: + Py_XDECREF(k); Py_XDECREF(ste); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 03:09:57 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 03:09:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Closed_reference_leak_of_variable_=27k=27_in_function_st?= =?utf-8?q?e=5Fnew_which_wasn=27t_decrefed?= Message-ID: <3XFWPx4L7ZzQbd@mail.python.org> http://hg.python.org/cpython/rev/a29854168241 changeset: 78945:a29854168241 parent: 78941:517aa5576ae3 parent: 78943:ad3824a90261 user: Christian Heimes date: Mon Sep 10 03:09:17 2012 +0200 summary: Closed reference leak of variable 'k' in function ste_new which wasn't decrefed in error cases files: Python/symtable.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -24,7 +24,7 @@ void *key, int lineno, int col_offset) { PySTEntryObject *ste = NULL; - PyObject *k; + PyObject *k = NULL; k = PyLong_FromVoidPtr(key); if (k == NULL) @@ -79,6 +79,7 @@ return ste; fail: + Py_XDECREF(k); Py_XDECREF(ste); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 03:50:57 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 03:50:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_out-of-bounce_write_?= =?utf-8?q?to_rawmode_buffer=2E_The_fixed_size_buffer_wasn=27t?= Message-ID: <3XFXKF18FXzNsb@mail.python.org> http://hg.python.org/cpython/rev/85cb90f79cbf changeset: 78946:85cb90f79cbf user: Christian Heimes date: Mon Sep 10 03:50:48 2012 +0200 summary: Fixed out-of-bounce write to rawmode buffer. The fixed size buffer wasn't enlarged for the new 'x' flag. The buffer may contain the 5 flags xrwa+ and the \0 byte files: Modules/_io/_iomodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/_io/_iomodule.c b/Modules/_io/_iomodule.c --- a/Modules/_io/_iomodule.c +++ b/Modules/_io/_iomodule.c @@ -229,7 +229,7 @@ int creating = 0, reading = 0, writing = 0, appending = 0, updating = 0; int text = 0, binary = 0, universal = 0; - char rawmode[5], *m; + char rawmode[6], *m; int line_buffering, isatty; PyObject *raw, *modeobj = NULL, *buffer = NULL, *wrapper = NULL; -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Sep 10 06:04:01 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 10 Sep 2012 06:04:01 +0200 Subject: [Python-checkins] Daily reference leaks (a29854168241): sum=2 Message-ID: results for a29854168241 on branch "default" -------------------------------------------- test_dbm leaked [0, 0, 2] references, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogPlcD_Z', '-x'] From python-checkins at python.org Mon Sep 10 11:48:50 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 11:48:50 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_memory_leak_in_error?= =?utf-8?q?_branch_of_formatfloat=28=29=2E_CID_719687?= Message-ID: <3XFkwf6VYPzQ8q@mail.python.org> http://hg.python.org/cpython/rev/a3e194661b5f changeset: 78947:a3e194661b5f user: Christian Heimes date: Mon Sep 10 11:48:41 2012 +0200 summary: Fixed memory leak in error branch of formatfloat(). CID 719687 files: Objects/unicodeobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -13238,8 +13238,10 @@ return -1; len = strlen(p); if (writer) { - if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1) + if (_PyUnicodeWriter_Prepare(writer, len, 127) == -1) { + PyMem_Free(p); return -1; + } unicode_write_cstr(writer->buffer, writer->pos, p, len); writer->pos += len; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 12:00:18 2012 From: python-checkins at python.org (matthias.klose) Date: Mon, 10 Sep 2012 12:00:18 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogLSBNZW50aW9uIF9o?= =?utf-8?q?eapq_in_Setup=2Edist=2E?= Message-ID: <3XFl9t3G6lzQh5@mail.python.org> http://hg.python.org/cpython/rev/d261defe4613 changeset: 78948:d261defe4613 branch: 2.7 parent: 78944:61446e56f683 user: doko at ubuntu.com date: Mon Sep 10 11:56:47 2012 +0200 summary: - Mention _heapq in Setup.dist. files: Modules/Setup.dist | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/Setup.dist b/Modules/Setup.dist --- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -177,6 +177,7 @@ #_testcapi _testcapimodule.c # Python C API test module #_random _randommodule.c # Random number generator #_collections _collectionsmodule.c # Container types +#_heapq _heapqmodule.c # Heapq type #itertools itertoolsmodule.c # Functions creating iterators for efficient looping #strop stropmodule.c # String manipulations #_functools _functoolsmodule.c # Tools for working with functions and callable objects -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 13:19:25 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 13:19:25 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Added_missing_?= =?utf-8?q?va=5Fend_in_error_branch_of_PyArg=5FUnpackTuple=28=29=2E_CID_48?= =?utf-8?q?6641?= Message-ID: <3XFmx91SZQzPG3@mail.python.org> http://hg.python.org/cpython/rev/71e854617297 changeset: 78949:71e854617297 branch: 3.2 parent: 78943:ad3824a90261 user: Christian Heimes date: Mon Sep 10 13:16:45 2012 +0200 summary: Added missing va_end in error branch of PyArg_UnpackTuple(). CID 486641 files: Python/getargs.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Python/getargs.c b/Python/getargs.c --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1725,6 +1725,7 @@ assert(min >= 0); assert(min <= max); if (!PyTuple_Check(args)) { + va_end(vargs); PyErr_SetString(PyExc_SystemError, "PyArg_UnpackTuple() argument list is not a tuple"); return 0; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 13:19:26 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 13:19:26 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Added_missing_va=5Fend_in_error_branch_of_PyArg=5FUnpack?= =?utf-8?q?Tuple=28=29=2E_CID_486641?= Message-ID: <3XFmxB72TJzQgH@mail.python.org> http://hg.python.org/cpython/rev/29abedd4f4bb changeset: 78950:29abedd4f4bb parent: 78947:a3e194661b5f parent: 78949:71e854617297 user: Christian Heimes date: Mon Sep 10 13:17:23 2012 +0200 summary: Added missing va_end in error branch of PyArg_UnpackTuple(). CID 486641 files: Python/getargs.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Python/getargs.c b/Python/getargs.c --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1742,6 +1742,7 @@ assert(min >= 0); assert(min <= max); if (!PyTuple_Check(args)) { + va_end(vargs); PyErr_SetString(PyExc_SystemError, "PyArg_UnpackTuple() argument list is not a tuple"); return 0; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 13:19:28 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 13:19:28 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Added_missing_?= =?utf-8?q?va=5Fend_in_error_branch_of_PyArg=5FUnpackTuple=28=29=2E_CID_48?= =?utf-8?q?6641?= Message-ID: <3XFmxD2mW6zQgW@mail.python.org> http://hg.python.org/cpython/rev/aa804ef5a6ca changeset: 78951:aa804ef5a6ca branch: 2.7 parent: 78944:61446e56f683 user: Christian Heimes date: Mon Sep 10 13:16:45 2012 +0200 summary: Added missing va_end in error branch of PyArg_UnpackTuple(). CID 486641 files: Python/getargs.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Python/getargs.c b/Python/getargs.c --- a/Python/getargs.c +++ b/Python/getargs.c @@ -1837,6 +1837,7 @@ assert(min >= 0); assert(min <= max); if (!PyTuple_Check(args)) { + va_end(vargs); PyErr_SetString(PyExc_SystemError, "PyArg_UnpackTuple() argument list is not a tuple"); return 0; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 13:19:30 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 13:19:30 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_merge?= Message-ID: <3XFmxG0mmgzQh3@mail.python.org> http://hg.python.org/cpython/rev/9c30a69c72ec changeset: 78952:9c30a69c72ec branch: 2.7 parent: 78951:aa804ef5a6ca parent: 78948:d261defe4613 user: Christian Heimes date: Mon Sep 10 13:19:15 2012 +0200 summary: merge files: Modules/Setup.dist | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/Setup.dist b/Modules/Setup.dist --- a/Modules/Setup.dist +++ b/Modules/Setup.dist @@ -177,6 +177,7 @@ #_testcapi _testcapimodule.c # Python C API test module #_random _randommodule.c # Random number generator #_collections _collectionsmodule.c # Container types +#_heapq _heapqmodule.c # Heapq type #itertools itertoolsmodule.c # Functions creating iterators for efficient looping #strop stropmodule.c # String manipulations #_functools _functoolsmodule.c # Tools for working with functions and callable objects -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 14:08:03 2012 From: python-checkins at python.org (richard.oudkerk) Date: Mon, 10 Sep 2012 14:08:03 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1OTAx?= =?utf-8?q?=3A_Change_example_to_use_byte_string_instead_of_string?= Message-ID: <3XFp1H1B7mzQfW@mail.python.org> http://hg.python.org/cpython/rev/ddb406904be1 changeset: 78953:ddb406904be1 branch: 3.2 parent: 78949:71e854617297 user: Richard Oudkerk date: Mon Sep 10 13:00:33 2012 +0100 summary: Issue #15901: Change example to use byte string instead of string files: Doc/library/multiprocessing.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1093,7 +1093,7 @@ n = Value('i', 7) x = Value(c_double, 1.0/3.0, lock=False) - s = Array('c', 'hello world', lock=lock) + s = Array('c', b'hello world', lock=lock) A = Array(Point, [(1.875,-6.25), (-5.75,2.0), (2.375,9.5)], lock=lock) p = Process(target=modify, args=(n, x, s, A)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 14:08:04 2012 From: python-checkins at python.org (richard.oudkerk) Date: Mon, 10 Sep 2012 14:08:04 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <3XFp1J5gkSzQgJ@mail.python.org> http://hg.python.org/cpython/rev/9def2209a839 changeset: 78954:9def2209a839 parent: 78950:29abedd4f4bb parent: 78953:ddb406904be1 user: Richard Oudkerk date: Mon Sep 10 13:06:02 2012 +0100 summary: Merge files: Doc/library/multiprocessing.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -1147,7 +1147,7 @@ n = Value('i', 7) x = Value(c_double, 1.0/3.0, lock=False) - s = Array('c', 'hello world', lock=lock) + s = Array('c', b'hello world', lock=lock) A = Array(Point, [(1.875,-6.25), (-5.75,2.0), (2.375,9.5)], lock=lock) p = Process(target=modify, args=(n, x, s, A)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 14:23:11 2012 From: python-checkins at python.org (matthias.klose) Date: Mon, 10 Sep 2012 14:23:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_backport_from_?= =?utf-8?q?the_trunk=2C_to_fix_test=5Ftools_with_srcdir_!=3D_builddir?= Message-ID: <3XFpLl1fz7zQh6@mail.python.org> http://hg.python.org/cpython/rev/5493299df0a0 changeset: 78955:5493299df0a0 branch: 3.2 parent: 78953:ddb406904be1 user: doko at ubuntu.com date: Mon Sep 10 14:19:42 2012 +0200 summary: backport from the trunk, to fix test_tools with srcdir != builddir changeset: 77827:c23b442b5d5e user: Antoine Pitrou date: Thu Jun 28 01:20:26 2012 +0200 summary: Avoid using scrdir, it's broken. changeset: 77826:f0e58e778215 user: Neil Schemenauer date: Wed Jun 27 15:58:37 2012 -0600 summary: Fix bug in test_tools that prevented building is separate directory. files: Lib/test/test_tools.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -18,8 +18,8 @@ # and run the tests in that case too? raise unittest.SkipTest('test irrelevant for an installed Python') -srcdir = sysconfig.get_config_var('projectbase') -basepath = os.path.join(os.getcwd(), srcdir, 'Tools') +basepath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + 'Tools') scriptsdir = os.path.join(basepath, 'scripts') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 14:38:10 2012 From: python-checkins at python.org (matthias.klose) Date: Mon, 10 Sep 2012 14:38:10 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_backport_from_?= =?utf-8?q?the_trunk=2C_to_fix_test=5Ftools_with_srcdir_!=3D_builddir?= Message-ID: <3XFph25b8ZzQWL@mail.python.org> http://hg.python.org/cpython/rev/6d0c54b99ca9 changeset: 78956:6d0c54b99ca9 branch: 2.7 parent: 78952:9c30a69c72ec user: doko at ubuntu.com date: Mon Sep 10 14:34:42 2012 +0200 summary: backport from the trunk, to fix test_tools with srcdir != builddir changeset: 77827:c23b442b5d5e user: Antoine Pitrou date: Thu Jun 28 01:20:26 2012 +0200 summary: Avoid using scrdir, it's broken. changeset: 77826:f0e58e778215 user: Neil Schemenauer date: Wed Jun 27 15:58:37 2012 -0600 summary: Fix bug in test_tools that prevented building is separate directory. files: Lib/test/test_tools.py | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_tools.py b/Lib/test/test_tools.py --- a/Lib/test/test_tools.py +++ b/Lib/test/test_tools.py @@ -15,8 +15,8 @@ # and run the tests in that case too? raise unittest.SkipTest('test irrelevant for an installed Python') -srcdir = sysconfig.get_config_var('projectbase') -basepath = os.path.join(os.getcwd(), srcdir, 'Tools') +basepath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), + 'Tools') class ReindentTests(unittest.TestCase): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 14:48:59 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 14:48:59 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Added_test_for_85cb90f79cb?= =?utf-8?q?f_and_see_how_the_code_handles_all_flags_at_once?= Message-ID: <3XFpwW68Z2zQgJ@mail.python.org> http://hg.python.org/cpython/rev/5a81a0836da1 changeset: 78957:5a81a0836da1 parent: 78954:9def2209a839 user: Christian Heimes date: Mon Sep 10 14:48:43 2012 +0200 summary: Added test for 85cb90f79cbf and see how the code handles all flags at once files: Lib/test/test_io.py | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -2887,6 +2887,11 @@ with self.open(support.TESTFN, 'rb') as f: self.assertEqual(b"spam", f.read()) + def test_open_allargs(self): + # there used to be a buffer overflow in the parser for rawmode + self.assertRaises(ValueError, self.open, support.TESTFN, 'rwax+') + + class CMiscIOTest(MiscIOTest): io = io -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 16:10:42 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 10 Sep 2012 16:10:42 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Null_merge_for_ddb406904be1_backport=2E?= Message-ID: <3XFrkp3NyqzQg3@mail.python.org> http://hg.python.org/cpython/rev/c18b15f2609e changeset: 78958:c18b15f2609e parent: 78957:5a81a0836da1 parent: 78955:5493299df0a0 user: R David Murray date: Mon Sep 10 10:10:13 2012 -0400 summary: Null merge for ddb406904be1 backport. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 16:17:33 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 10 Sep 2012 16:17:33 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE0NjQ5OiBjbGFy?= =?utf-8?q?ify_DocTestSuite_error_when_there_are_no_docstrings=2E?= Message-ID: <3XFrtj2bt4zM0Q@mail.python.org> http://hg.python.org/cpython/rev/d012f645b8b2 changeset: 78959:d012f645b8b2 branch: 3.2 parent: 78955:5493299df0a0 user: R David Murray date: Mon Sep 10 10:15:58 2012 -0400 summary: #14649: clarify DocTestSuite error when there are no docstrings. Also adds tests to verify the documented behavior (which is probably a bug, as indicated in the added comments). Patch by Chris Jerdonek. files: Doc/library/doctest.rst | 10 ++++ Lib/doctest.py | 7 ++- Lib/test/sample_doctest_no_docstrings.py | 12 +++++ Lib/test/sample_doctest_no_doctests.py | 15 +++++++ Lib/test/test_doctest.py | 25 ++++++++++++ Lib/test/test_zipimport_support.py | 21 +++++++-- 6 files changed, 84 insertions(+), 6 deletions(-) diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -1024,6 +1024,16 @@ This function uses the same search technique as :func:`testmod`. + .. note:: + Unlike :func:`testmod` and :class:`DocTestFinder`, this function raises + a :exc:`ValueError` if *module* contains no docstrings. You can prevent + this error by passing a :class:`DocTestFinder` instance as the + *test_finder* argument with its *exclude_empty* keyword argument set + to ``False``:: + + >>> finder = doctest.DocTestFinder(exclude_empty=False) + >>> suite = doctest.DocTestSuite(test_finder=finder) + Under the covers, :func:`DocTestSuite` creates a :class:`unittest.TestSuite` out of :class:`doctest.DocTestCase` instances, and :class:`DocTestCase` is a diff --git a/Lib/doctest.py b/Lib/doctest.py --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2333,7 +2333,12 @@ elif not tests: # Why do we want to do this? Because it reveals a bug that might # otherwise be hidden. - raise ValueError(module, "has no tests") + # It is probably a bug that this exception is not also raised if the + # number of doctest examples in tests is zero (i.e. if no doctest + # examples were found). However, we should probably not be raising + # an exception at all here, though it is too late to make this change + # for a maintenance release. See also issue #14649. + raise ValueError(module, "has no docstrings") tests.sort() suite = unittest.TestSuite() diff --git a/Lib/test/sample_doctest_no_docstrings.py b/Lib/test/sample_doctest_no_docstrings.py new file mode 100644 --- /dev/null +++ b/Lib/test/sample_doctest_no_docstrings.py @@ -0,0 +1,12 @@ +# This is a sample module used for testing doctest. +# +# This module is for testing how doctest handles a module with no +# docstrings. + + +class Foo(object): + + # A class with no docstring. + + def __init__(self): + pass diff --git a/Lib/test/sample_doctest_no_doctests.py b/Lib/test/sample_doctest_no_doctests.py new file mode 100644 --- /dev/null +++ b/Lib/test/sample_doctest_no_doctests.py @@ -0,0 +1,15 @@ +"""This is a sample module used for testing doctest. + +This module is for testing how doctest handles a module with docstrings +but no doctest examples. + +""" + + +class Foo(object): + """A docstring with no doctest examples. + + """ + + def __init__(self): + pass diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -1984,6 +1984,31 @@ >>> suite.run(unittest.TestResult()) + The module need not contain any doctest examples: + + >>> suite = doctest.DocTestSuite('test.sample_doctest_no_doctests') + >>> suite.run(unittest.TestResult()) + + + However, if DocTestSuite finds no docstrings, it raises an error: + + >>> try: + ... doctest.DocTestSuite('test.sample_doctest_no_docstrings') + ... except ValueError as e: + ... error = e + + >>> print(error.args[1]) + has no docstrings + + You can prevent this error by passing a DocTestFinder instance with + the `exclude_empty` keyword argument set to False: + + >>> finder = doctest.DocTestFinder(exclude_empty=False) + >>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings', + ... test_finder=finder) + >>> suite.run(unittest.TestResult()) + + We can use the current module: >>> suite = test.sample_doctest.test_suite() diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py --- a/Lib/test/test_zipimport_support.py +++ b/Lib/test/test_zipimport_support.py @@ -29,7 +29,8 @@ # test_cmd_line_script (covers the zipimport support in runpy) # Retrieve some helpers from other test cases -from test import test_doctest, sample_doctest +from test import (test_doctest, sample_doctest, sample_doctest_no_doctests, + sample_doctest_no_docstrings) def _run_object_doctest(obj, module): @@ -105,16 +106,26 @@ "test_zipped_doctest") test_src = test_src.replace("test.sample_doctest", "sample_zipped_doctest") - sample_src = inspect.getsource(sample_doctest) - sample_src = sample_src.replace("test.test_doctest", - "test_zipped_doctest") + # The sample doctest files rewritten to include in the zipped version. + sample_sources = {} + for mod in [sample_doctest, sample_doctest_no_doctests, + sample_doctest_no_docstrings]: + src = inspect.getsource(mod) + src = src.replace("test.test_doctest", "test_zipped_doctest") + # Rewrite the module name so that, for example, + # "test.sample_doctest" becomes "sample_zipped_doctest". + mod_name = mod.__name__.split(".")[-1] + mod_name = mod_name.replace("sample_", "sample_zipped_") + sample_sources[mod_name] = src + with temp_dir() as d: script_name = make_script(d, 'test_zipped_doctest', test_src) zip_name, run_name = make_zip_script(d, 'test_zip', script_name) z = zipfile.ZipFile(zip_name, 'a') - z.writestr("sample_zipped_doctest.py", sample_src) + for mod_name, src in sample_sources.items(): + z.writestr(mod_name + ".py", src) z.close() if verbose: zip_file = zipfile.ZipFile(zip_name, 'r') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 16:17:35 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 10 Sep 2012 16:17:35 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2314649=3A_clarify_DocTestSuite_error_when_there_?= =?utf-8?q?are_no_docstrings=2E?= Message-ID: <3XFrtl1YSXzQVV@mail.python.org> http://hg.python.org/cpython/rev/6544fc92b528 changeset: 78960:6544fc92b528 parent: 78958:c18b15f2609e parent: 78959:d012f645b8b2 user: R David Murray date: Mon Sep 10 10:16:46 2012 -0400 summary: Merge #14649: clarify DocTestSuite error when there are no docstrings. Also adds tests to verify the documented behavior (which is probably a bug, as indicated in the added comments). Patch by Chris Jerdonek. files: Doc/library/doctest.rst | 10 ++++ Lib/doctest.py | 7 ++- Lib/test/sample_doctest_no_docstrings.py | 12 +++++ Lib/test/sample_doctest_no_doctests.py | 15 +++++++ Lib/test/test_doctest.py | 25 ++++++++++++ Lib/test/test_zipimport_support.py | 21 +++++++-- 6 files changed, 84 insertions(+), 6 deletions(-) diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -1024,6 +1024,16 @@ This function uses the same search technique as :func:`testmod`. + .. note:: + Unlike :func:`testmod` and :class:`DocTestFinder`, this function raises + a :exc:`ValueError` if *module* contains no docstrings. You can prevent + this error by passing a :class:`DocTestFinder` instance as the + *test_finder* argument with its *exclude_empty* keyword argument set + to ``False``:: + + >>> finder = doctest.DocTestFinder(exclude_empty=False) + >>> suite = doctest.DocTestSuite(test_finder=finder) + Under the covers, :func:`DocTestSuite` creates a :class:`unittest.TestSuite` out of :class:`doctest.DocTestCase` instances, and :class:`DocTestCase` is a diff --git a/Lib/doctest.py b/Lib/doctest.py --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2334,7 +2334,12 @@ elif not tests: # Why do we want to do this? Because it reveals a bug that might # otherwise be hidden. - raise ValueError(module, "has no tests") + # It is probably a bug that this exception is not also raised if the + # number of doctest examples in tests is zero (i.e. if no doctest + # examples were found). However, we should probably not be raising + # an exception at all here, though it is too late to make this change + # for a maintenance release. See also issue #14649. + raise ValueError(module, "has no docstrings") tests.sort() suite = unittest.TestSuite() diff --git a/Lib/test/sample_doctest_no_docstrings.py b/Lib/test/sample_doctest_no_docstrings.py new file mode 100644 --- /dev/null +++ b/Lib/test/sample_doctest_no_docstrings.py @@ -0,0 +1,12 @@ +# This is a sample module used for testing doctest. +# +# This module is for testing how doctest handles a module with no +# docstrings. + + +class Foo(object): + + # A class with no docstring. + + def __init__(self): + pass diff --git a/Lib/test/sample_doctest_no_doctests.py b/Lib/test/sample_doctest_no_doctests.py new file mode 100644 --- /dev/null +++ b/Lib/test/sample_doctest_no_doctests.py @@ -0,0 +1,15 @@ +"""This is a sample module used for testing doctest. + +This module is for testing how doctest handles a module with docstrings +but no doctest examples. + +""" + + +class Foo(object): + """A docstring with no doctest examples. + + """ + + def __init__(self): + pass diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -1986,6 +1986,31 @@ >>> suite.run(unittest.TestResult()) + The module need not contain any doctest examples: + + >>> suite = doctest.DocTestSuite('test.sample_doctest_no_doctests') + >>> suite.run(unittest.TestResult()) + + + However, if DocTestSuite finds no docstrings, it raises an error: + + >>> try: + ... doctest.DocTestSuite('test.sample_doctest_no_docstrings') + ... except ValueError as e: + ... error = e + + >>> print(error.args[1]) + has no docstrings + + You can prevent this error by passing a DocTestFinder instance with + the `exclude_empty` keyword argument set to False: + + >>> finder = doctest.DocTestFinder(exclude_empty=False) + >>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings', + ... test_finder=finder) + >>> suite.run(unittest.TestResult()) + + We can use the current module: >>> suite = test.sample_doctest.test_suite() diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py --- a/Lib/test/test_zipimport_support.py +++ b/Lib/test/test_zipimport_support.py @@ -29,7 +29,8 @@ # test_cmd_line_script (covers the zipimport support in runpy) # Retrieve some helpers from other test cases -from test import test_doctest, sample_doctest +from test import (test_doctest, sample_doctest, sample_doctest_no_doctests, + sample_doctest_no_docstrings) def _run_object_doctest(obj, module): @@ -105,16 +106,26 @@ "test_zipped_doctest") test_src = test_src.replace("test.sample_doctest", "sample_zipped_doctest") - sample_src = inspect.getsource(sample_doctest) - sample_src = sample_src.replace("test.test_doctest", - "test_zipped_doctest") + # The sample doctest files rewritten to include in the zipped version. + sample_sources = {} + for mod in [sample_doctest, sample_doctest_no_doctests, + sample_doctest_no_docstrings]: + src = inspect.getsource(mod) + src = src.replace("test.test_doctest", "test_zipped_doctest") + # Rewrite the module name so that, for example, + # "test.sample_doctest" becomes "sample_zipped_doctest". + mod_name = mod.__name__.split(".")[-1] + mod_name = mod_name.replace("sample_", "sample_zipped_") + sample_sources[mod_name] = src + with temp_dir() as d: script_name = make_script(d, 'test_zipped_doctest', test_src) zip_name, run_name = make_zip_script(d, 'test_zip', script_name) z = zipfile.ZipFile(zip_name, 'a') - z.writestr("sample_zipped_doctest.py", sample_src) + for mod_name, src in sample_sources.items(): + z.writestr(mod_name + ".py", src) z.close() if verbose: zip_file = zipfile.ZipFile(zip_name, 'r') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 16:17:36 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 10 Sep 2012 16:17:36 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE0NjQ5OiBjbGFy?= =?utf-8?q?ify_DocTestSuite_error_when_there_are_no_docstrings=2E?= Message-ID: <3XFrtm6NG4zQVV@mail.python.org> http://hg.python.org/cpython/rev/b48ef168d8c5 changeset: 78961:b48ef168d8c5 branch: 2.7 parent: 78956:6d0c54b99ca9 user: R David Murray date: Mon Sep 10 10:17:13 2012 -0400 summary: #14649: clarify DocTestSuite error when there are no docstrings. Also adds tests to verify the documented behavior (which is probably a bug, as indicated in the added comments). Patch by Chris Jerdonek. files: Doc/library/doctest.rst | 10 +++++++ Lib/doctest.py | 7 ++++- Lib/test/test_doctest.py | 25 ++++++++++++++++++ Lib/test/test_zipimport_support.py | 21 +++++++++++--- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -1060,6 +1060,16 @@ .. versionchanged:: 2.5 The parameter *encoding* was added. + .. note:: + Unlike :func:`testmod` and :class:`DocTestFinder`, this function raises + a :exc:`ValueError` if *module* contains no docstrings. You can prevent + this error by passing a :class:`DocTestFinder` instance as the + *test_finder* argument with its *exclude_empty* keyword argument set + to ``False``:: + + >>> finder = doctest.DocTestFinder(exclude_empty=False) + >>> suite = doctest.DocTestSuite(test_finder=finder) + .. function:: DocTestSuite([module][, globs][, extraglobs][, test_finder][, setUp][, tearDown][, checker]) diff --git a/Lib/doctest.py b/Lib/doctest.py --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2381,7 +2381,12 @@ elif not tests: # Why do we want to do this? Because it reveals a bug that might # otherwise be hidden. - raise ValueError(module, "has no tests") + # It is probably a bug that this exception is not also raised if the + # number of doctest examples in tests is zero (i.e. if no doctest + # examples were found). However, we should probably not be raising + # an exception at all here, though it is too late to make this change + # for a maintenance release. See also issue #14649. + raise ValueError(module, "has no docstrings") tests.sort() suite = unittest.TestSuite() diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2006,6 +2006,31 @@ >>> suite.run(unittest.TestResult()) + The module need not contain any doctest examples: + + >>> suite = doctest.DocTestSuite('test.sample_doctest_no_doctests') + >>> suite.run(unittest.TestResult()) + + + However, if DocTestSuite finds no docstrings, it raises an error: + + >>> try: + ... doctest.DocTestSuite('test.sample_doctest_no_docstrings') + ... except ValueError as e: + ... error = e + + >>> print(error.args[1]) + has no docstrings + + You can prevent this error by passing a DocTestFinder instance with + the `exclude_empty` keyword argument set to False: + + >>> finder = doctest.DocTestFinder(exclude_empty=False) + >>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings', + ... test_finder=finder) + >>> suite.run(unittest.TestResult()) + + We can use the current module: >>> suite = test.sample_doctest.test_suite() diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py --- a/Lib/test/test_zipimport_support.py +++ b/Lib/test/test_zipimport_support.py @@ -29,7 +29,8 @@ # test_cmd_line_script (covers the zipimport support in runpy) # Retrieve some helpers from other test cases -from test import test_doctest, sample_doctest +from test import (test_doctest, sample_doctest, sample_doctest_no_doctests, + sample_doctest_no_docstrings) from test.test_importhooks import ImportHooksBaseTestCase @@ -99,16 +100,26 @@ "test_zipped_doctest") test_src = test_src.replace("test.sample_doctest", "sample_zipped_doctest") - sample_src = inspect.getsource(sample_doctest) - sample_src = sample_src.replace("test.test_doctest", - "test_zipped_doctest") + # The sample doctest files rewritten to include in the zipped version. + sample_sources = {} + for mod in [sample_doctest, sample_doctest_no_doctests, + sample_doctest_no_docstrings]: + src = inspect.getsource(mod) + src = src.replace("test.test_doctest", "test_zipped_doctest") + # Rewrite the module name so that, for example, + # "test.sample_doctest" becomes "sample_zipped_doctest". + mod_name = mod.__name__.split(".")[-1] + mod_name = mod_name.replace("sample_", "sample_zipped_") + sample_sources[mod_name] = src + with temp_dir() as d: script_name = make_script(d, 'test_zipped_doctest', test_src) zip_name, run_name = make_zip_script(d, 'test_zip', script_name) z = zipfile.ZipFile(zip_name, 'a') - z.writestr("sample_zipped_doctest.py", sample_src) + for mod_name, src in sample_sources.items(): + z.writestr(mod_name + ".py", src) z.close() if verbose: zip_file = zipfile.ZipFile(zip_name, 'r') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 16:54:14 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 16:54:14 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fixed_memory_l?= =?utf-8?q?eak_in_error_branch_of_parsestrplus=2E_CID_715374_Variable_s_go?= =?utf-8?q?ing?= Message-ID: <3XFsj220RtzQFd@mail.python.org> http://hg.python.org/cpython/rev/4a343636c8ca changeset: 78962:4a343636c8ca branch: 3.2 parent: 78959:d012f645b8b2 user: Christian Heimes date: Mon Sep 10 16:52:42 2012 +0200 summary: Fixed memory leak in error branch of parsestrplus. CID 715374 Variable s going out of scope leaks the storage it points to. files: Python/ast.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -3395,6 +3395,7 @@ goto onError; if (*bytesmode != subbm) { ast_error(n, "cannot mix bytes and nonbytes literals"); + Py_DECREF(s); goto onError; } if (PyBytes_Check(v) && PyBytes_Check(s)) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 16:54:15 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 16:54:15 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Fixed_memory_leak_in_error_branch_of_parsestrplus=2E_CID?= =?utf-8?q?_715374_Variable_s_going?= Message-ID: <3XFsj36sHDzQXs@mail.python.org> http://hg.python.org/cpython/rev/2c9f1a578861 changeset: 78963:2c9f1a578861 parent: 78960:6544fc92b528 parent: 78962:4a343636c8ca user: Christian Heimes date: Mon Sep 10 16:53:28 2012 +0200 summary: Fixed memory leak in error branch of parsestrplus. CID 715374 Variable s going out of scope leaks the storage it points to. files: Python/ast.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Python/ast.c b/Python/ast.c --- a/Python/ast.c +++ b/Python/ast.c @@ -3846,6 +3846,7 @@ goto onError; if (*bytesmode != subbm) { ast_error(c, n, "cannot mix bytes and nonbytes literals"); + Py_DECREF(s); goto onError; } if (PyBytes_Check(v) && PyBytes_Check(s)) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 17:01:40 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 17:01:40 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fixed_memory_l?= =?utf-8?q?eak_in_error_branch_of_object=5Frepr_which_may_leak_a_reference?= =?utf-8?q?_to?= Message-ID: <3XFssc1ClQzQhR@mail.python.org> http://hg.python.org/cpython/rev/302561c9387a changeset: 78964:302561c9387a branch: 3.2 parent: 78962:4a343636c8ca user: Christian Heimes date: Mon Sep 10 16:57:36 2012 +0200 summary: Fixed memory leak in error branch of object_repr which may leak a reference to mod when type_name returns NULL. CID 715371 files: Objects/typeobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2925,8 +2925,10 @@ mod = NULL; } name = type_name(type, NULL); - if (name == NULL) + if (name == NULL) { + Py_XDECREF(mod); return NULL; + } if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins")) rtn = PyUnicode_FromFormat("<%U.%U object at %p>", mod, name, self); else -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 17:01:41 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 17:01:41 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fixed_memory_l?= =?utf-8?q?eak_in_error_branch_of_object=5Frepr_which_may_leak_a_reference?= =?utf-8?q?_to?= Message-ID: <3XFssd57Q9zQjS@mail.python.org> http://hg.python.org/cpython/rev/a1671c795934 changeset: 78965:a1671c795934 branch: 2.7 parent: 78956:6d0c54b99ca9 user: Christian Heimes date: Mon Sep 10 16:57:36 2012 +0200 summary: Fixed memory leak in error branch of object_repr which may leak a reference to mod when type_name returns NULL. CID 715371 files: Objects/typeobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -2984,8 +2984,10 @@ mod = NULL; } name = type_name(type, NULL); - if (name == NULL) + if (name == NULL) { + Py_XDECREF(mod); return NULL; + } if (mod != NULL && strcmp(PyString_AS_STRING(mod), "__builtin__")) rtn = PyString_FromFormat("<%s.%s object at %p>", PyString_AS_STRING(mod), -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 17:01:43 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 17:01:43 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Fixed_memory_leak_in_error_branch_of_object=5Frepr_which?= =?utf-8?q?_may_leak_a_reference_to?= Message-ID: <3XFssg16GvzQjj@mail.python.org> http://hg.python.org/cpython/rev/f9b95ffd24ce changeset: 78966:f9b95ffd24ce parent: 78963:2c9f1a578861 parent: 78964:302561c9387a user: Christian Heimes date: Mon Sep 10 17:00:30 2012 +0200 summary: Fixed memory leak in error branch of object_repr which may leak a reference to mod when type_qualname returns NULL. CID 715371 files: Objects/typeobject.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Objects/typeobject.c b/Objects/typeobject.c --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -3130,8 +3130,10 @@ mod = NULL; } name = type_qualname(type, NULL); - if (name == NULL) + if (name == NULL) { + Py_XDECREF(mod); return NULL; + } if (mod != NULL && PyUnicode_CompareWithASCIIString(mod, "builtins")) rtn = PyUnicode_FromFormat("<%U.%U object at %p>", mod, name, self); else -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 17:01:44 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 17:01:44 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_merge?= Message-ID: <3XFssh5HL4zQhT@mail.python.org> http://hg.python.org/cpython/rev/cac191b37e78 changeset: 78967:cac191b37e78 branch: 2.7 parent: 78965:a1671c795934 parent: 78961:b48ef168d8c5 user: Christian Heimes date: Mon Sep 10 17:01:21 2012 +0200 summary: merge files: Doc/library/doctest.rst | 10 +++++++ Lib/doctest.py | 7 ++++- Lib/test/test_doctest.py | 25 ++++++++++++++++++ Lib/test/test_zipimport_support.py | 21 +++++++++++--- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/Doc/library/doctest.rst b/Doc/library/doctest.rst --- a/Doc/library/doctest.rst +++ b/Doc/library/doctest.rst @@ -1060,6 +1060,16 @@ .. versionchanged:: 2.5 The parameter *encoding* was added. + .. note:: + Unlike :func:`testmod` and :class:`DocTestFinder`, this function raises + a :exc:`ValueError` if *module* contains no docstrings. You can prevent + this error by passing a :class:`DocTestFinder` instance as the + *test_finder* argument with its *exclude_empty* keyword argument set + to ``False``:: + + >>> finder = doctest.DocTestFinder(exclude_empty=False) + >>> suite = doctest.DocTestSuite(test_finder=finder) + .. function:: DocTestSuite([module][, globs][, extraglobs][, test_finder][, setUp][, tearDown][, checker]) diff --git a/Lib/doctest.py b/Lib/doctest.py --- a/Lib/doctest.py +++ b/Lib/doctest.py @@ -2381,7 +2381,12 @@ elif not tests: # Why do we want to do this? Because it reveals a bug that might # otherwise be hidden. - raise ValueError(module, "has no tests") + # It is probably a bug that this exception is not also raised if the + # number of doctest examples in tests is zero (i.e. if no doctest + # examples were found). However, we should probably not be raising + # an exception at all here, though it is too late to make this change + # for a maintenance release. See also issue #14649. + raise ValueError(module, "has no docstrings") tests.sort() suite = unittest.TestSuite() diff --git a/Lib/test/test_doctest.py b/Lib/test/test_doctest.py --- a/Lib/test/test_doctest.py +++ b/Lib/test/test_doctest.py @@ -2006,6 +2006,31 @@ >>> suite.run(unittest.TestResult()) + The module need not contain any doctest examples: + + >>> suite = doctest.DocTestSuite('test.sample_doctest_no_doctests') + >>> suite.run(unittest.TestResult()) + + + However, if DocTestSuite finds no docstrings, it raises an error: + + >>> try: + ... doctest.DocTestSuite('test.sample_doctest_no_docstrings') + ... except ValueError as e: + ... error = e + + >>> print(error.args[1]) + has no docstrings + + You can prevent this error by passing a DocTestFinder instance with + the `exclude_empty` keyword argument set to False: + + >>> finder = doctest.DocTestFinder(exclude_empty=False) + >>> suite = doctest.DocTestSuite('test.sample_doctest_no_docstrings', + ... test_finder=finder) + >>> suite.run(unittest.TestResult()) + + We can use the current module: >>> suite = test.sample_doctest.test_suite() diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py --- a/Lib/test/test_zipimport_support.py +++ b/Lib/test/test_zipimport_support.py @@ -29,7 +29,8 @@ # test_cmd_line_script (covers the zipimport support in runpy) # Retrieve some helpers from other test cases -from test import test_doctest, sample_doctest +from test import (test_doctest, sample_doctest, sample_doctest_no_doctests, + sample_doctest_no_docstrings) from test.test_importhooks import ImportHooksBaseTestCase @@ -99,16 +100,26 @@ "test_zipped_doctest") test_src = test_src.replace("test.sample_doctest", "sample_zipped_doctest") - sample_src = inspect.getsource(sample_doctest) - sample_src = sample_src.replace("test.test_doctest", - "test_zipped_doctest") + # The sample doctest files rewritten to include in the zipped version. + sample_sources = {} + for mod in [sample_doctest, sample_doctest_no_doctests, + sample_doctest_no_docstrings]: + src = inspect.getsource(mod) + src = src.replace("test.test_doctest", "test_zipped_doctest") + # Rewrite the module name so that, for example, + # "test.sample_doctest" becomes "sample_zipped_doctest". + mod_name = mod.__name__.split(".")[-1] + mod_name = mod_name.replace("sample_", "sample_zipped_") + sample_sources[mod_name] = src + with temp_dir() as d: script_name = make_script(d, 'test_zipped_doctest', test_src) zip_name, run_name = make_zip_script(d, 'test_zip', script_name) z = zipfile.ZipFile(zip_name, 'a') - z.writestr("sample_zipped_doctest.py", sample_src) + for mod_name, src in sample_sources.items(): + z.writestr(mod_name + ".py", src) z.close() if verbose: zip_file = zipfile.ZipFile(zip_name, 'r') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 17:20:58 2012 From: python-checkins at python.org (r.david.murray) Date: Mon, 10 Sep 2012 17:20:58 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE0NjQ5OiBhZGQg?= =?utf-8?q?sample_files_omitted_from_previous_checkin=2E?= Message-ID: <3XFtHt5H7tzQhj@mail.python.org> http://hg.python.org/cpython/rev/c5fc49bc7a5f changeset: 78968:c5fc49bc7a5f branch: 2.7 user: R David Murray date: Mon Sep 10 11:20:47 2012 -0400 summary: #14649: add sample files omitted from previous checkin. files: Lib/test/sample_doctest_no_docstrings.py | 12 +++++++++ Lib/test/sample_doctest_no_doctests.py | 15 ++++++++++++ 2 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Lib/test/sample_doctest_no_docstrings.py b/Lib/test/sample_doctest_no_docstrings.py new file mode 100644 --- /dev/null +++ b/Lib/test/sample_doctest_no_docstrings.py @@ -0,0 +1,12 @@ +# This is a sample module used for testing doctest. +# +# This module is for testing how doctest handles a module with no +# docstrings. + + +class Foo(object): + + # A class with no docstring. + + def __init__(self): + pass diff --git a/Lib/test/sample_doctest_no_doctests.py b/Lib/test/sample_doctest_no_doctests.py new file mode 100644 --- /dev/null +++ b/Lib/test/sample_doctest_no_doctests.py @@ -0,0 +1,15 @@ +"""This is a sample module used for testing doctest. + +This module is for testing how doctest handles a module with docstrings +but no doctest examples. + +""" + + +class Foo(object): + """A docstring with no doctest examples. + + """ + + def __init__(self): + pass -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 17:46:57 2012 From: python-checkins at python.org (christian.heimes) Date: Mon, 10 Sep 2012 17:46:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fixed_reference_leak_in_er?= =?utf-8?q?ror_branch_of_=5Fbufferedreader=5Fread=5Fall=28=29=2E_The?= Message-ID: <3XFtss5GDgzNgN@mail.python.org> http://hg.python.org/cpython/rev/71d94e79b0c3 changeset: 78969:71d94e79b0c3 parent: 78966:f9b95ffd24ce user: Christian Heimes date: Mon Sep 10 17:46:09 2012 +0200 summary: Fixed reference leak in error branch of _bufferedreader_read_all(). The variable data can contain a bytes object but it wasn't cleaned up when PyList_New() failed. CID 715364 files: Modules/_io/bufferedio.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -1499,8 +1499,10 @@ } chunks = PyList_New(0); - if (chunks == NULL) + if (chunks == NULL) { + Py_XDECREF(data); return NULL; + } while (1) { if (data) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 19:42:06 2012 From: python-checkins at python.org (stefan.krah) Date: Mon, 10 Sep 2012 19:42:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315882=3A_Change_?= =?utf-8?q?=5Fdecimal_to_accept_any_coefficient_tuple_when?= Message-ID: <3XFxQk5GjlzNsb@mail.python.org> http://hg.python.org/cpython/rev/97e53273f423 changeset: 78970:97e53273f423 user: Stefan Krah date: Mon Sep 10 19:34:58 2012 +0200 summary: Issue #15882: Change _decimal to accept any coefficient tuple when constructing infinities. This is done for backwards compatibility with decimal.py: Infinity coefficients are undefined in _decimal (in accordance with the specification). files: Lib/test/test_decimal.py | 17 ++++++++++------- Misc/NEWS | 4 ++++ Modules/_decimal/_decimal.c | 7 +++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -1992,7 +1992,8 @@ d = Decimal("-4.34913534E-17") self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) - # XXX non-compliant infinity payload. + # The '0' coefficient is implementation specific to decimal.py. + # It has no meaning in the C-version and is ignored there. d = Decimal("Infinity") self.assertEqual(d.as_tuple(), (0, (0,), 'F') ) @@ -2012,12 +2013,14 @@ d = Decimal( (1, (), 'n') ) self.assertEqual(d.as_tuple(), (1, (), 'n') ) - # XXX coefficient in infinity should raise an error - if self.decimal == P: - d = Decimal( (0, (4, 5, 3, 4), 'F') ) - self.assertEqual(d.as_tuple(), (0, (0,), 'F')) - d = Decimal( (1, (0, 2, 7, 1), 'F') ) - self.assertEqual(d.as_tuple(), (1, (0,), 'F')) + # For infinities, decimal.py has always silently accepted any + # coefficient tuple. + d = Decimal( (0, (0,), 'F') ) + self.assertEqual(d.as_tuple(), (0, (0,), 'F')) + d = Decimal( (0, (4, 5, 3, 4), 'F') ) + self.assertEqual(d.as_tuple(), (0, (0,), 'F')) + d = Decimal( (1, (0, 2, 7, 1), 'F') ) + self.assertEqual(d.as_tuple(), (1, (0,), 'F')) def test_subclassing(self): # Different behaviours when subclassing Decimal diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -21,6 +21,10 @@ Library ------- +- Issue #15882: Change _decimal to accept any coefficient tuple when + constructing infinities. This is done for backwards compatibility + with decimal.py: Infinity coefficients are undefined in _decimal + (in accordance with the specification). - Issue #15876: Fix a refleak in the curses module: window.encoding. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2364,6 +2364,7 @@ long sign, l; mpd_ssize_t exp = 0; Py_ssize_t i, mem, tsize; + int is_infinite = 0; int n; assert(PyTuple_Check(dectuple)); @@ -2399,6 +2400,7 @@ /* special */ if (PyUnicode_CompareWithASCIIString(tmp, "F") == 0) { strcat(sign_special, "Inf"); + is_infinite = 1; } else if (PyUnicode_CompareWithASCIIString(tmp, "n") == 0) { strcat(sign_special, "NaN"); @@ -2470,6 +2472,11 @@ "coefficient must be a tuple of digits"); goto error; } + if (is_infinite) { + /* accept but ignore any well-formed coefficient for compatibility + with decimal.py */ + continue; + } *cp++ = (char)l + '0'; } *cp = '\0'; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 20:20:19 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 20:20:19 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE1Njc2OiBQcm9w?= =?utf-8?q?er_attribution_in_Misc/ACKS?= Message-ID: <3XFyGq1QmdzQ4M@mail.python.org> http://hg.python.org/cpython/rev/9ed2e8307e60 changeset: 78971:9ed2e8307e60 branch: 2.7 parent: 78968:c5fc49bc7a5f user: Jesus Cea date: Mon Sep 10 20:18:43 2012 +0200 summary: #15676: Proper attribution in Misc/ACKS files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -939,6 +939,7 @@ John Williams Sue Williams Gerald S. Williams +Steven Willis Frank Willison Greg V. Wilson J Derek Wilson -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 20:20:20 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 20:20:20 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1Njc2OiBQcm9w?= =?utf-8?q?er_attribution_in_Misc/ACKS?= Message-ID: <3XFyGr4Sh4zQ4M@mail.python.org> http://hg.python.org/cpython/rev/4f21f7532038 changeset: 78972:4f21f7532038 branch: 3.2 parent: 78964:302561c9387a user: Jesus Cea date: Mon Sep 10 20:19:25 2012 +0200 summary: #15676: Proper attribution in Misc/ACKS files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1029,6 +1029,7 @@ John Williams Sue Williams Gerald S. Williams +Steven Willis Frank Willison Greg V. Wilson J Derek Wilson -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 20:20:22 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 20:20:22 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_MERGE=3A_=2315676=3A_Proper_attribution_in_Misc/ACKS?= Message-ID: <3XFyGt0VxFzQ7J@mail.python.org> http://hg.python.org/cpython/rev/4fdc6c501e63 changeset: 78973:4fdc6c501e63 parent: 78970:97e53273f423 parent: 78972:4f21f7532038 user: Jesus Cea date: Mon Sep 10 20:20:02 2012 +0200 summary: MERGE: #15676: Proper attribution in Misc/ACKS files: Misc/ACKS | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1139,6 +1139,7 @@ Jason Williams John Williams Sue Williams +Steven Willis Frank Willison Greg V. Wilson J Derek Wilson -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 21:04:58 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 21:04:58 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogQ2xvc2VzICMxNTkw?= =?utf-8?q?8=3A_SHA1_crashes_in_64_bits_when_the_string_to_hash_is_bigger_?= =?utf-8?q?than?= Message-ID: <3XFzGL5w97zQD6@mail.python.org> http://hg.python.org/cpython/rev/a13bfc238f27 changeset: 78974:a13bfc238f27 branch: 2.7 parent: 78971:9ed2e8307e60 user: Jesus Cea date: Mon Sep 10 21:04:42 2012 +0200 summary: Closes #15908: SHA1 crashes in 64 bits when the string to hash is bigger than 2**32 bytes files: Lib/test/test_hashlib.py | 8 ++++++++ Misc/NEWS | 3 +++ Modules/shamodule.c | 19 ++++++++++++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -228,6 +228,14 @@ self.check('sha1', "a" * 1000000, "34aa973cd4c4daa4f61eeb2bdbad27316534016f") + @precisionbigmemtest(size=_4G + 5, memuse=1) + def test_case_sha1_huge(self, size): + if size == _4G + 5: + try: + self.check('sha1', 'A'*size, + '87d745c50e6b2879ffa0fb2c930e9fbfe0dc9a5b') + except OverflowError: + pass # 32-bit arch # use the examples from Federal Information Processing Standards # Publication 180-2, Secure Hash Standard, 2002 August 1 diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -244,6 +244,9 @@ - Issue #14888: Fix misbehaviour of the _md5 module when called on data larger than 2**32 bytes. +- Issue #15908: Fix misbehaviour of the sha1 module when called on data + larger than 2**32 bytes. + - Issue #14875: Use float('inf') instead of float('1e66666') in the json module. - Issue #14572: Prevent build failures with pre-3.5.0 versions of diff --git a/Modules/shamodule.c b/Modules/shamodule.c --- a/Modules/shamodule.c +++ b/Modules/shamodule.c @@ -536,6 +536,8 @@ static char *kwlist[] = {"string", NULL}; SHAobject *new; Py_buffer view = { 0 }; + Py_ssize_t n; + unsigned char *buf; if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s*:new", kwlist, &view)) { @@ -554,10 +556,21 @@ PyBuffer_Release(&view); return NULL; } - if (view.len > 0) { - sha_update(new, (unsigned char*)view.buf, - Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); + + n = view.len; + buf = (unsigned char *) view.buf; + while (n > 0) { + Py_ssize_t nbytes; + if (n > INT_MAX) + nbytes = INT_MAX; + else + nbytes = n; + sha_update(new, buf, + Py_SAFE_DOWNCAST(nbytes, Py_ssize_t, unsigned int)); + buf += nbytes; + n -= nbytes; } + PyBuffer_Release(&view); return (PyObject *)new; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 21:39:27 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 21:39:27 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogQ2xvc2VzICMxNTkx?= =?utf-8?q?0=3A_MD5_and_SHA1_crash_when_=22updated=22_with_strings_bigger_?= =?utf-8?q?than_2**32?= Message-ID: <3XG02721QZzQKy@mail.python.org> http://hg.python.org/cpython/rev/4d36e56b56d9 changeset: 78975:4d36e56b56d9 branch: 2.7 user: Jesus Cea date: Mon Sep 10 21:39:07 2012 +0200 summary: Closes #15910: MD5 and SHA1 crash when "updated" with strings bigger than 2**32 bytes files: Lib/test/test_hashlib.py | 33 ++++++++++++++++++++++++++++ Misc/NEWS | 3 ++ Modules/md5module.c | 17 ++++++++++++- Modules/shamodule.c | 17 ++++++++++++- 4 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -167,6 +167,21 @@ % (name, hash_object_constructor, computed, len(data), digest)) + def check_update(self, name, data, digest): + constructors = self.constructors_to_test[name] + # 2 is for hashlib.name(...) and hashlib.new(name, ...) + self.assertGreaterEqual(len(constructors), 2) + for hash_object_constructor in constructors: + h = hash_object_constructor() + h.update(data) + computed = h.hexdigest() + self.assertEqual( + computed, digest, + "Hash algorithm %s using %s when updated returned hexdigest" + " %r for %d byte input data that should have hashed to %r." + % (name, hash_object_constructor, + computed, len(data), digest)) + def check_unicode(self, algorithm_name): # Unicode objects are not allowed as input. expected = hashlib.new(algorithm_name, str(u'spam')).hexdigest() @@ -200,6 +215,15 @@ except OverflowError: pass # 32-bit arch + @precisionbigmemtest(size=_4G + 5, memuse=1) + def test_case_md5_huge_update(self, size): + if size == _4G + 5: + try: + self.check_update('md5', 'A'*size, + 'c9af2dff37468ce5dfee8f2cfc0a9c6d') + except OverflowError: + pass # 32-bit arch + @precisionbigmemtest(size=_4G - 1, memuse=1) def test_case_md5_uintmax(self, size): if size == _4G - 1: @@ -237,6 +261,15 @@ except OverflowError: pass # 32-bit arch + @precisionbigmemtest(size=_4G + 5, memuse=1) + def test_case_sha1_huge_update(self, size): + if size == _4G + 5: + try: + self.check_update('sha1', 'A'*size, + '87d745c50e6b2879ffa0fb2c930e9fbfe0dc9a5b') + except OverflowError: + pass # 32-bit arch + # use the examples from Federal Information Processing Standards # Publication 180-2, Secure Hash Standard, 2002 August 1 # http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -247,6 +247,9 @@ - Issue #15908: Fix misbehaviour of the sha1 module when called on data larger than 2**32 bytes. +- Issue #15910: Fix misbehaviour of _md5 and sha1 modules when "updating" + on data larger than 2**32 bytes. + - Issue #14875: Use float('inf') instead of float('1e66666') in the json module. - Issue #14572: Prevent build failures with pre-3.5.0 versions of diff --git a/Modules/md5module.c b/Modules/md5module.c --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -51,12 +51,25 @@ md5_update(md5object *self, PyObject *args) { Py_buffer view; + Py_ssize_t n; + unsigned char *buf; if (!PyArg_ParseTuple(args, "s*:update", &view)) return NULL; - md5_append(&self->md5, (unsigned char*)view.buf, - Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); + n = view.len; + buf = (unsigned char *) view.buf; + while (n > 0) { + Py_ssize_t nbytes; + if (n > INT_MAX) + nbytes = INT_MAX; + else + nbytes = n; + md5_append(&self->md5, buf, + Py_SAFE_DOWNCAST(nbytes, Py_ssize_t, unsigned int)); + buf += nbytes; + n -= nbytes; + } PyBuffer_Release(&view); Py_RETURN_NONE; diff --git a/Modules/shamodule.c b/Modules/shamodule.c --- a/Modules/shamodule.c +++ b/Modules/shamodule.c @@ -429,12 +429,25 @@ SHA_update(SHAobject *self, PyObject *args) { Py_buffer view; + Py_ssize_t n; + unsigned char *buf; if (!PyArg_ParseTuple(args, "s*:update", &view)) return NULL; - sha_update(self, (unsigned char*)view.buf, - Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int)); + n = view.len; + buf = (unsigned char *) view.buf; + while (n > 0) { + Py_ssize_t nbytes; + if (n > INT_MAX) + nbytes = INT_MAX; + else + nbytes = n; + sha_update(self, buf, + Py_SAFE_DOWNCAST(nbytes, Py_ssize_t, unsigned int)); + buf += nbytes; + n -= nbytes; + } PyBuffer_Release(&view); Py_RETURN_NONE; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 22:46:01 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 22:46:01 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE1Njc2OiBtbWFw?= =?utf-8?q?=3A_add_empty_file_check_prior_to_offset_check_=3C-_Previous_pa?= =?utf-8?q?tch_was?= Message-ID: <3XG1Vx0vK8zQXw@mail.python.org> http://hg.python.org/cpython/rev/25d477647a2d changeset: 78976:25d477647a2d branch: 2.7 user: Jesus Cea date: Mon Sep 10 22:45:47 2012 +0200 summary: #15676: mmap: add empty file check prior to offset check <- Previous patch was incomplete files: Lib/test/test_mmap.py | 21 +++++++++------------ Modules/mmapmodule.c | 5 +++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -469,18 +469,15 @@ def test_empty_file (self): f = open (TESTFN, 'w+b') f.close() - f = open(TESTFN, "rb") - try: - m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) - m.close() - f.close() - self.fail("should not have been able to mmap empty file") - except ValueError as e: - f.close() - self.assertEqual(e.message, "cannot mmap an empty file") - except: - f.close() - self.fail("unexpected exception: " + str(e)) + with open(TESTFN, "rb") as f : + try: + m = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ) + m.close() + self.fail("should not have been able to mmap empty file") + except ValueError as e: + self.assertEqual(e.message, "cannot mmap an empty file") + except: + self.fail("unexpected exception: " + str(e)) def test_offset (self): f = open (TESTFN, 'w+b') diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1388,6 +1388,11 @@ } size = (((PY_LONG_LONG) high) << 32) + low; + if (size == 0) { + PyErr_SetString(PyExc_ValueError, + "cannot mmap an empty file"); + return NULL; + } if (offset >= size) { PyErr_SetString(PyExc_ValueError, "mmap offset is greater than file size"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 22:50:45 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 22:50:45 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1Njc2OiBtbWFw?= =?utf-8?q?=3A_add_empty_file_check_prior_to_offset_check_=3C-_Previous_pa?= =?utf-8?q?tch_was?= Message-ID: <3XG1cP1mD2zQXK@mail.python.org> http://hg.python.org/cpython/rev/88a88c32661e changeset: 78977:88a88c32661e branch: 3.2 parent: 78972:4f21f7532038 user: Jesus Cea date: Mon Sep 10 22:49:50 2012 +0200 summary: #15676: mmap: add empty file check prior to offset check <- Previous patch was incomplete files: Lib/test/test_mmap.py | 10 +++++----- Modules/mmapmodule.c | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -462,11 +462,11 @@ def test_empty_file (self): f = open (TESTFN, 'w+b') f.close() - f = open(TESTFN, "rb") - self.assertRaisesRegex(ValueError, - "cannot mmap an empty file", - mmap.mmap, f.fileno(), 0, access=mmap.ACCESS_READ) - f.close() + with open(TESTFN, "rb") as f : + self.assertRaisesRegex(ValueError, + "cannot mmap an empty file", + mmap.mmap, f.fileno(), 0, + access=mmap.ACCESS_READ) def test_offset (self): f = open (TESTFN, 'w+b') diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1342,6 +1342,11 @@ } size = (((PY_LONG_LONG) high) << 32) + low; + if (size == 0) { + PyErr_SetString(PyExc_ValueError, + "cannot mmap an empty file"); + return NULL; + } if (offset >= size) { PyErr_SetString(PyExc_ValueError, "mmap offset is greater than file size"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 22:50:46 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 22:50:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_=2315676=3A_mmap=3A_add_empty_file_check_prior_to_offset?= =?utf-8?q?_check_=3C-_Previous_patch_was?= Message-ID: <3XG1cQ6CXBzQZR@mail.python.org> http://hg.python.org/cpython/rev/0ac94ae29abe changeset: 78978:0ac94ae29abe parent: 78973:4fdc6c501e63 parent: 78977:88a88c32661e user: Jesus Cea date: Mon Sep 10 22:50:21 2012 +0200 summary: #15676: mmap: add empty file check prior to offset check <- Previous patch was incomplete files: Lib/test/test_mmap.py | 10 +++++----- Modules/mmapmodule.c | 5 +++++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_mmap.py b/Lib/test/test_mmap.py --- a/Lib/test/test_mmap.py +++ b/Lib/test/test_mmap.py @@ -491,11 +491,11 @@ def test_empty_file (self): f = open (TESTFN, 'w+b') f.close() - f = open(TESTFN, "rb") - self.assertRaisesRegex(ValueError, - "cannot mmap an empty file", - mmap.mmap, f.fileno(), 0, access=mmap.ACCESS_READ) - f.close() + with open(TESTFN, "rb") as f : + self.assertRaisesRegex(ValueError, + "cannot mmap an empty file", + mmap.mmap, f.fileno(), 0, + access=mmap.ACCESS_READ) def test_offset (self): f = open (TESTFN, 'w+b') diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1364,6 +1364,11 @@ } size = (((PY_LONG_LONG) high) << 32) + low; + if (size == 0) { + PyErr_SetString(PyExc_ValueError, + "cannot mmap an empty file"); + return NULL; + } if (offset >= size) { PyErr_SetString(PyExc_ValueError, "mmap offset is greater than file size"); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 22:58:51 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 22:58:51 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE1Njc2OiBtbWFw?= =?utf-8?q?=3A_add_empty_file_check_prior_to_offset_check_=3C-_Previous_pa?= =?utf-8?q?tch_was?= Message-ID: <3XG1nl3qmKzQVD@mail.python.org> http://hg.python.org/cpython/rev/39efccf7a167 changeset: 78979:39efccf7a167 branch: 2.7 parent: 78976:25d477647a2d user: Jesus Cea date: Mon Sep 10 22:57:34 2012 +0200 summary: #15676: mmap: add empty file check prior to offset check <- Previous patch was incomplete (fix 2) files: Modules/mmapmodule.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1391,6 +1391,7 @@ if (size == 0) { PyErr_SetString(PyExc_ValueError, "cannot mmap an empty file"); + Py_DECREF(m_obj); return NULL; } if (offset >= size) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 22:58:53 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 22:58:53 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1Njc2OiBtbWFw?= =?utf-8?q?=3A_add_empty_file_check_prior_to_offset_check_=3C-_Previous_pa?= =?utf-8?q?tch_was?= Message-ID: <3XG1nn0J4NzQY5@mail.python.org> http://hg.python.org/cpython/rev/56a2e862561c changeset: 78980:56a2e862561c branch: 3.2 parent: 78977:88a88c32661e user: Jesus Cea date: Mon Sep 10 22:58:07 2012 +0200 summary: #15676: mmap: add empty file check prior to offset check <- Previous patch was incomplete (fix 2) files: Modules/mmapmodule.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1345,6 +1345,7 @@ if (size == 0) { PyErr_SetString(PyExc_ValueError, "cannot mmap an empty file"); + Py_DECREF(m_obj); return NULL; } if (offset >= size) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Sep 10 22:58:54 2012 From: python-checkins at python.org (jesus.cea) Date: Mon, 10 Sep 2012 22:58:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_MERGE=3A_=2315676=3A_mmap=3A_add_empty_file_check_prior_?= =?utf-8?q?to_offset_check_=3C-_Previous?= Message-ID: <3XG1np4v0FzQVD@mail.python.org> http://hg.python.org/cpython/rev/306b2ecb1a3e changeset: 78981:306b2ecb1a3e parent: 78978:0ac94ae29abe parent: 78980:56a2e862561c user: Jesus Cea date: Mon Sep 10 22:58:35 2012 +0200 summary: MERGE: #15676: mmap: add empty file check prior to offset check <- Previous patch was incomplete (fix 2) files: Modules/mmapmodule.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Modules/mmapmodule.c b/Modules/mmapmodule.c --- a/Modules/mmapmodule.c +++ b/Modules/mmapmodule.c @@ -1367,6 +1367,7 @@ if (size == 0) { PyErr_SetString(PyExc_ValueError, "cannot mmap an empty file"); + Py_DECREF(m_obj); return NULL; } if (offset >= size) { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 02:23:59 2012 From: python-checkins at python.org (jesus.cea) Date: Tue, 11 Sep 2012 02:23:59 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogQ2xvc2VzICMxNTc5?= =?utf-8?q?3=3A_Stack_corruption_in_ssl=2ERAND=5Fegd=28=29=2E_Python_2=2E7?= =?utf-8?q?_hasn=27t_any_issue?= Message-ID: <3XG6LR18W7zP53@mail.python.org> http://hg.python.org/cpython/rev/706115cb2cdb changeset: 78982:706115cb2cdb branch: 2.7 parent: 78979:39efccf7a167 user: Jesus Cea date: Tue Sep 11 01:55:04 2012 +0200 summary: Closes #15793: Stack corruption in ssl.RAND_egd(). Python 2.7 hasn't any issue about this, but add a test just to be sure files: Lib/test/test_ssl.py | 8 ++------ 1 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -95,12 +95,8 @@ sys.stdout.write("\n RAND_status is %d (%s)\n" % (v, (v and "sufficient randomness") or "insufficient randomness")) - try: - ssl.RAND_egd(1) - except TypeError: - pass - else: - print "didn't raise TypeError" + self.assertRaises(TypeError, ssl.RAND_egd, 1) + self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1) ssl.RAND_add("this is a random string", 75.0) def test_parse_cert(self): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 02:24:00 2012 From: python-checkins at python.org (jesus.cea) Date: Tue, 11 Sep 2012 02:24:00 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogQ2xvc2VzICMxNTc5?= =?utf-8?q?3=3A_Stack_corruption_in_ssl=2ERAND=5Fegd=28=29?= Message-ID: <3XG6LS6drtzPpX@mail.python.org> http://hg.python.org/cpython/rev/827bb0554f1f changeset: 78983:827bb0554f1f branch: 3.2 parent: 78980:56a2e862561c user: Jesus Cea date: Tue Sep 11 02:00:58 2012 +0200 summary: Closes #15793: Stack corruption in ssl.RAND_egd() files: Lib/test/test_ssl.py | 8 ++------ Misc/NEWS | 3 +++ Modules/_ssl.c | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -103,12 +103,8 @@ sys.stdout.write("\n RAND_status is %d (%s)\n" % (v, (v and "sufficient randomness") or "insufficient randomness")) - try: - ssl.RAND_egd(1) - except TypeError: - pass - else: - print("didn't raise TypeError") + self.assertRaises(TypeError, ssl.RAND_egd, 1) + self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1) ssl.RAND_add("this is a random string", 75.0) def test_parse_cert(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -154,6 +154,9 @@ - Issue #13579: string.Formatter now understands the 'a' conversion specifier. +- Issue #15793: Stack corruption in ssl.RAND_egd(). + Patch by Serhiy Storchaka. + - Issue #15595: Fix subprocess.Popen(universal_newlines=True) for certain locales (utf-16 and utf-32 family). Patch by Chris Jerdonek. diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1917,7 +1917,7 @@ PyObject *path; int bytes; - if (!PyArg_ParseTuple(args, "O&|i:RAND_egd", + if (!PyArg_ParseTuple(args, "O&:RAND_egd", PyUnicode_FSConverter, &path)) return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 02:24:03 2012 From: python-checkins at python.org (jesus.cea) Date: Tue, 11 Sep 2012 02:24:03 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_MERGE=3A_Closes_=2315793=3A_Stack_corruption_in_ssl=2ERA?= =?utf-8?b?TkRfZWdkKCk=?= Message-ID: <3XG6LW0KkVzPpX@mail.python.org> http://hg.python.org/cpython/rev/7619a400d318 changeset: 78984:7619a400d318 parent: 78981:306b2ecb1a3e parent: 78983:827bb0554f1f user: Jesus Cea date: Tue Sep 11 02:08:48 2012 +0200 summary: MERGE: Closes #15793: Stack corruption in ssl.RAND_egd() files: Lib/test/test_ssl.py | 8 ++------ Misc/NEWS | 3 +++ Modules/_ssl.c | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -125,12 +125,8 @@ else: self.assertRaises(ssl.SSLError, ssl.RAND_bytes, 16) - try: - ssl.RAND_egd(1) - except TypeError: - pass - else: - print("didn't raise TypeError") + self.assertRaises(TypeError, ssl.RAND_egd, 1) + self.assertRaises(TypeError, ssl.RAND_egd, 'foo', 1) ssl.RAND_add("this is a random string", 75.0) def test_parse_cert(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -210,6 +210,9 @@ - Issue #13579: string.Formatter now understands the 'a' conversion specifier. +- Issue #15793: Stack corruption in ssl.RAND_egd(). + Patch by Serhiy Storchaka. + - Issue #15595: Fix subprocess.Popen(universal_newlines=True) for certain locales (utf-16 and utf-32 family). Patch by Chris Jerdonek. diff --git a/Modules/_ssl.c b/Modules/_ssl.c --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -2481,7 +2481,7 @@ PyObject *path; int bytes; - if (!PyArg_ParseTuple(args, "O&|i:RAND_egd", + if (!PyArg_ParseTuple(args, "O&:RAND_egd", PyUnicode_FSConverter, &path)) return NULL; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 03:09:13 2012 From: python-checkins at python.org (r.david.murray) Date: Tue, 11 Sep 2012 03:09:13 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_=2315886=3A_remove_redunda?= =?utf-8?q?nt_phrase?= Message-ID: <3XG7Ld0FfkzPGC@mail.python.org> http://hg.python.org/cpython/rev/d7ea7ec671ba changeset: 78985:d7ea7ec671ba user: R David Murray date: Mon Sep 10 21:08:50 2012 -0400 summary: #15886: remove redundant phrase files: Doc/library/os.rst | 5 ++--- 1 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -1855,9 +1855,8 @@ :attr:`st_mtime`, :attr:`st_ctime`. More items may be added at the end by some implementations. - This function can support :ref:`specifying a file descriptor - `, :ref:`specifying a file descriptor ` and :ref:`not - following symlinks `. + This function can support :ref:`specifying a file descriptor ` and + :ref:`not following symlinks `. .. index:: module: stat -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 04:28:41 2012 From: python-checkins at python.org (ezio.melotti) Date: Tue, 11 Sep 2012 04:28:41 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?hooks=3A_Remove_unused_import_and_cle?= =?utf-8?q?an_up_whitespace=2E?= Message-ID: <3XG96K1XlNzPS8@mail.python.org> http://hg.python.org/hooks/rev/72aaeb80a55a changeset: 83:72aaeb80a55a user: Ezio Melotti date: Tue Sep 11 05:28:30 2012 +0300 summary: Remove unused import and clean up whitespace. files: checkheads.py | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/checkheads.py b/checkheads.py --- a/checkheads.py +++ b/checkheads.py @@ -9,8 +9,6 @@ pretxnchangegroup.checkheads = python:/home/hg/repos/hooks/checkheads.py:hook """ -from collections import defaultdict - from mercurial.node import bin, nullrev from mercurial import util @@ -24,7 +22,7 @@ newcsets = range(start, end) # The rev numbers of the changegroup parents (not in the changegroup) parents = set() - + for n in newcsets: for p in changelog.parentrevs(n): if p == nullrev: @@ -51,5 +49,3 @@ ui.warn('* Please run "hg pull" and then merge at least two of:\n') ui.warn('* ' + ', '.join(str(repo[h]) for h in pheads) + '\n') return True - - -- Repository URL: http://hg.python.org/hooks From solipsis at pitrou.net Tue Sep 11 06:05:26 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 11 Sep 2012 06:05:26 +0200 Subject: [Python-checkins] Daily reference leaks (d7ea7ec671ba): sum=0 Message-ID: results for d7ea7ec671ba on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogwKpx7J', '-x'] From python-checkins at python.org Tue Sep 11 12:20:31 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 11 Sep 2012 12:20:31 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogRml4IGlzc3VlICMx?= =?utf-8?q?5899=3A_Make_the_unicode=2Erst_doctests_pass=2E_Patch_by_Chris_?= =?utf-8?q?Jerdonek=2E?= Message-ID: <3XGMZl5cCKzQB3@mail.python.org> http://hg.python.org/cpython/rev/8a40bc71c072 changeset: 78986:8a40bc71c072 branch: 3.2 parent: 78983:827bb0554f1f user: Senthil Kumaran date: Tue Sep 11 03:17:52 2012 -0700 summary: Fix issue #15899: Make the unicode.rst doctests pass. Patch by Chris Jerdonek. files: Doc/howto/unicode.rst | 27 +++++++++++++-------------- 1 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -257,13 +257,13 @@ 'REPLACEMENT CHARACTER'), or 'ignore' (just leave the character out of the Unicode result). The following examples show the differences:: - >>> b'\x80abc'.decode("utf-8", "strict") + >>> b'\x80abc'.decode("utf-8", "strict") #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? - UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: - unexpected code byte + ... + UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: + invalid start byte >>> b'\x80abc'.decode("utf-8", "replace") - '?abc' + '?abc' >>> b'\x80abc'.decode("utf-8", "ignore") 'abc' @@ -301,11 +301,11 @@ >>> u = chr(40960) + 'abcd' + chr(1972) >>> u.encode('utf-8') b'\xea\x80\x80abcd\xde\xb4' - >>> u.encode('ascii') + >>> u.encode('ascii') #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? + ... UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in - position 0: ordinal not in range(128) + position 0: ordinal not in range(128) >>> u.encode('ascii', 'ignore') b'abcd' >>> u.encode('ascii', 'replace') @@ -331,12 +331,11 @@ not four:: >>> s = "a\xac\u1234\u20ac\U00008000" - ^^^^ two-digit hex escape - ^^^^^ four-digit Unicode escape - ^^^^^^^^^^ eight-digit Unicode escape - >>> for c in s: print(ord(c), end=" ") - ... - 97 172 4660 8364 32768 + ... # ^^^^ two-digit hex escape + ... # ^^^^^^ four-digit Unicode escape + ... # ^^^^^^^^^^ eight-digit Unicode escape + >>> [ord(c) for c in s] + [97, 172, 4660, 8364, 32768] Using escape sequences for code points greater than 127 is fine in small doses, but becomes an annoyance if you're using many accented characters, as you would -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 12:20:33 2012 From: python-checkins at python.org (senthil.kumaran) Date: Tue, 11 Sep 2012 12:20:33 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_merge=2E__Fix_issue_=2315899=3A_Make_the_unicode=2Erst_d?= =?utf-8?q?octests_pass=2E_Patch_by_Chris?= Message-ID: <3XGMZn2jX4zQ9X@mail.python.org> http://hg.python.org/cpython/rev/1d9e89f6abec changeset: 78987:1d9e89f6abec parent: 78985:d7ea7ec671ba parent: 78986:8a40bc71c072 user: Senthil Kumaran date: Tue Sep 11 03:20:22 2012 -0700 summary: merge. Fix issue #15899: Make the unicode.rst doctests pass. Patch by Chris Jerdonek. files: Doc/howto/unicode.rst | 27 +++++++++++++-------------- 1 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -257,13 +257,13 @@ 'REPLACEMENT CHARACTER'), or 'ignore' (just leave the character out of the Unicode result). The following examples show the differences:: - >>> b'\x80abc'.decode("utf-8", "strict") + >>> b'\x80abc'.decode("utf-8", "strict") #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? - UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: - unexpected code byte + ... + UnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: + invalid start byte >>> b'\x80abc'.decode("utf-8", "replace") - '?abc' + '?abc' >>> b'\x80abc'.decode("utf-8", "ignore") 'abc' @@ -301,11 +301,11 @@ >>> u = chr(40960) + 'abcd' + chr(1972) >>> u.encode('utf-8') b'\xea\x80\x80abcd\xde\xb4' - >>> u.encode('ascii') + >>> u.encode('ascii') #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? + ... UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in - position 0: ordinal not in range(128) + position 0: ordinal not in range(128) >>> u.encode('ascii', 'ignore') b'abcd' >>> u.encode('ascii', 'replace') @@ -331,12 +331,11 @@ not four:: >>> s = "a\xac\u1234\u20ac\U00008000" - ^^^^ two-digit hex escape - ^^^^^ four-digit Unicode escape - ^^^^^^^^^^ eight-digit Unicode escape - >>> for c in s: print(ord(c), end=" ") - ... - 97 172 4660 8364 32768 + ... # ^^^^ two-digit hex escape + ... # ^^^^^^ four-digit Unicode escape + ... # ^^^^^^^^^^ eight-digit Unicode escape + >>> [ord(c) for c in s] + [97, 172, 4660, 8364, 32768] Using escape sequences for code points greater than 127 is fine in small doses, but becomes an annoyance if you're using many accented characters, as you would -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 14:03:35 2012 From: python-checkins at python.org (christian.heimes) Date: Tue, 11 Sep 2012 14:03:35 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315900=3A_Fixed_re?= =?utf-8?q?ference_leak_in_PyUnicode=5FTranslateCharmap=28=29?= Message-ID: <3XGPsg2V1nzQKb@mail.python.org> http://hg.python.org/cpython/rev/4f2811e5e462 changeset: 78988:4f2811e5e462 user: Christian Heimes date: Tue Sep 11 14:03:25 2012 +0200 summary: Issue #15900: Fixed reference leak in PyUnicode_TranslateCharmap() files: Misc/NEWS | 2 ++ Objects/unicodeobject.c | 11 +++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #15900: Fixed reference leak in PyUnicode_TranslateCharmap(). + - Issue #15839: Convert SystemErrors in super() to RuntimeErrors. - Issue #15846: Fix SystemError which happened when using ast.parse in an diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -8585,10 +8585,13 @@ PyObject *mapping, const char *errors) { + PyObject *result; PyObject *unicode = PyUnicode_FromUnicode(p, size); if (!unicode) return NULL; - return _PyUnicode_TranslateCharmap(unicode, mapping, errors); + result = _PyUnicode_TranslateCharmap(unicode, mapping, errors); + Py_DECREF(unicode); + return result; } PyObject * @@ -8600,14 +8603,10 @@ str = PyUnicode_FromObject(str); if (str == NULL) - goto onError; + return NULL; result = _PyUnicode_TranslateCharmap(str, mapping, errors); Py_DECREF(str); return result; - - onError: - Py_XDECREF(str); - return NULL; } static Py_UCS4 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 14:12:33 2012 From: python-checkins at python.org (christian.heimes) Date: Tue, 11 Sep 2012 14:12:33 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Spelling_past_tense_-=3E_p?= =?utf-8?q?resent_tense?= Message-ID: <3XGQ412cBbzQM4@mail.python.org> http://hg.python.org/cpython/rev/f1a31d9d36e6 changeset: 78989:f1a31d9d36e6 user: Christian Heimes date: Tue Sep 11 14:08:49 2012 +0200 summary: Spelling past tense -> present tense files: Misc/NEWS | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,7 @@ Core and Builtins ----------------- -- Issue #15900: Fixed reference leak in PyUnicode_TranslateCharmap(). +- Issue #15900: Fix reference leak in PyUnicode_TranslateCharmap(). - Issue #15839: Convert SystemErrors in super() to RuntimeErrors. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 14:12:35 2012 From: python-checkins at python.org (christian.heimes) Date: Tue, 11 Sep 2012 14:12:35 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315895=3A_Fix_FILE?= =?utf-8?q?_pointer_leak_in_PyRun=5FSimpleFileExFlags=28=29_when_filename?= Message-ID: <3XGQ436sptzQQH@mail.python.org> http://hg.python.org/cpython/rev/4754c4a710e6 changeset: 78990:4754c4a710e6 user: Christian Heimes date: Tue Sep 11 14:11:03 2012 +0200 summary: Issue #15895: Fix FILE pointer leak in PyRun_SimpleFileExFlags() when filename points to a pyc/pyo file and closeit is false. files: Misc/NEWS | 3 +++ Python/pythonrun.c | 6 +++++- 2 files changed, 8 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #15895: Fix FILE pointer leak in PyRun_SimpleFileExFlags() when + filename points to a pyc/pyo file and closeit is false. + - Issue #15900: Fix reference leak in PyUnicode_TranslateCharmap(). - Issue #15839: Convert SystemErrors in super() to RuntimeErrors. diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1385,7 +1385,7 @@ { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, ret; + int set_file_name = 0, close_own_fp = 0, ret; size_t len; m = PyImport_AddModule("__main__"); @@ -1419,6 +1419,7 @@ ret = -1; goto done; } + close_own_fp = 1; /* Turn on optimization if a .pyo file is given */ if (strcmp(ext, ".pyo") == 0) Py_OptimizeFlag = 1; @@ -1449,6 +1450,9 @@ Py_DECREF(v); ret = 0; done: + if (close_own_fp) { + fclose(fp); + } if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); return ret; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 15:47:39 2012 From: python-checkins at python.org (christian.heimes) Date: Tue, 11 Sep 2012 15:47:39 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315895=3A_my_analy?= =?utf-8?q?sis_was_slightly_off=2E_The_FILE_pointer_is_only_leaked?= Message-ID: <3XGS9l6DmxzQVY@mail.python.org> http://hg.python.org/cpython/rev/c3539eb02470 changeset: 78991:c3539eb02470 user: Christian Heimes date: Tue Sep 11 15:47:28 2012 +0200 summary: Issue #15895: my analysis was slightly off. The FILE pointer is only leaked when set_main_loader() fails for a pyc file with closeit=0. In the success case run_pyc_file() does its own cleanup of the fp. I've changed the code to use another FILE ptr for pyc files and moved the fclose() to PyRun_SimpleFileExFlags() to make it more obvious what's happening. files: Misc/NEWS | 3 ++- Python/pythonrun.c | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,7 +10,8 @@ Core and Builtins ----------------- -- Issue #15895: Fix FILE pointer leak in PyRun_SimpleFileExFlags() when +- Issue #15895: Fix FILE pointer leak in one error branch of + PyRun_SimpleFileExFlags() when filename points to a pyc/pyo file and closeit is false. - Issue #15900: Fix reference leak in PyUnicode_TranslateCharmap(). diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1385,7 +1385,7 @@ { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, close_own_fp = 0, ret; + int set_file_name = 0, ret; size_t len; m = PyImport_AddModule("__main__"); @@ -1411,15 +1411,15 @@ len = strlen(filename); ext = filename + len - (len > 4 ? 4 : 0); if (maybe_pyc_file(fp, filename, ext, closeit)) { + FILE *pyc_fp; /* Try to run a pyc file. First, re-open in binary */ if (closeit) fclose(fp); - if ((fp = fopen(filename, "rb")) == NULL) { + if ((pyc_fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); ret = -1; goto done; } - close_own_fp = 1; /* Turn on optimization if a .pyo file is given */ if (strcmp(ext, ".pyo") == 0) Py_OptimizeFlag = 1; @@ -1427,9 +1427,11 @@ if (set_main_loader(d, filename, "SourcelessFileLoader") < 0) { fprintf(stderr, "python: failed to set __main__.__loader__\n"); ret = -1; + fclose(pyc_fp); goto done; } - v = run_pyc_file(fp, filename, d, d, flags); + v = run_pyc_file(pyc_fp, filename, d, d, flags); + fclose(pyc_fp); } else { /* When running from stdin, leave __main__.__loader__ alone */ if (strcmp(filename, "") != 0 && @@ -1450,9 +1452,6 @@ Py_DECREF(v); ret = 0; done: - if (close_own_fp) { - fclose(fp); - } if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); return ret; @@ -1999,7 +1998,6 @@ (void) PyMarshal_ReadLongFromFile(fp); (void) PyMarshal_ReadLongFromFile(fp); v = PyMarshal_ReadLastObjectFromFile(fp); - fclose(fp); if (v == NULL || !PyCode_Check(v)) { Py_XDECREF(v); PyErr_SetString(PyExc_RuntimeError, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 17:31:29 2012 From: python-checkins at python.org (christian.heimes) Date: Tue, 11 Sep 2012 17:31:29 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fix_null_point?= =?utf-8?q?er_dereferencing_in_structmember=2Ec_PyMember=5FSetOne=28=29_fo?= =?utf-8?b?ciBUX0NIQVIu?= Message-ID: <3XGVTY2dm9zQFB@mail.python.org> http://hg.python.org/cpython/rev/afe55cd04119 changeset: 78992:afe55cd04119 branch: 3.2 parent: 78986:8a40bc71c072 user: Christian Heimes date: Tue Sep 11 17:30:53 2012 +0200 summary: Fix null pointer dereferencing in structmember.c PyMember_SetOne() for T_CHAR. _PyUnicode_AsStringAndSize() can return NULL without touching the len argument. Also remove unnecessary PyUnicode_Check(), _PyUnicode_AsStringAndSize() performance the test again. CID 486815 files: Python/structmember.c | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Python/structmember.c b/Python/structmember.c --- a/Python/structmember.c +++ b/Python/structmember.c @@ -254,12 +254,8 @@ char *string; Py_ssize_t len; - if (!PyUnicode_Check(v)) { - PyErr_BadArgument(); - return -1; - } string = _PyUnicode_AsStringAndSize(v, &len); - if (len != 1) { + if (string == NULL || len != 1) { PyErr_BadArgument(); return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 17:31:32 2012 From: python-checkins at python.org (christian.heimes) Date: Tue, 11 Sep 2012 17:31:32 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Fix_null_pointer_dereferencing_in_structmember=2Ec_PyMem?= =?utf-8?b?YmVyX1NldE9uZSgpIGZvciBUX0NIQVIu?= Message-ID: <3XGVTc5zkyzQNr@mail.python.org> http://hg.python.org/cpython/rev/59ec0b9ff724 changeset: 78993:59ec0b9ff724 parent: 78991:c3539eb02470 parent: 78992:afe55cd04119 user: Christian Heimes date: Tue Sep 11 17:31:08 2012 +0200 summary: Fix null pointer dereferencing in structmember.c PyMember_SetOne() for T_CHAR. _PyUnicode_AsStringAndSize() can return NULL without touching the len argument. Also remove unnecessary PyUnicode_Check(), _PyUnicode_AsStringAndSize() performance the test again. CID 486815 files: Python/structmember.c | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Python/structmember.c b/Python/structmember.c --- a/Python/structmember.c +++ b/Python/structmember.c @@ -254,12 +254,8 @@ char *string; Py_ssize_t len; - if (!PyUnicode_Check(v)) { - PyErr_BadArgument(); - return -1; - } string = _PyUnicode_AsStringAndSize(v, &len); - if (len != 1) { + if (string == NULL || len != 1) { PyErr_BadArgument(); return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 18:05:24 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 11 Sep 2012 18:05:24 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_remove_useless_and_defined?= =?utf-8?q?_initialization_=28closes_=2315921=29?= Message-ID: <3XGWDh4bFrzQXX@mail.python.org> http://hg.python.org/cpython/rev/6cdc72f4d82c changeset: 78994:6cdc72f4d82c parent: 78991:c3539eb02470 user: Benjamin Peterson date: Tue Sep 11 12:05:05 2012 -0400 summary: remove useless and defined initialization (closes #15921) files: Modules/selectmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -239,7 +239,7 @@ #else /* 64-bit OS X has struct timeval.tv_usec as an int (and thus still 4 bytes as required), but no longer defined by a long. */ - long tv_usec = tv.tv_usec; + long tv_usec; if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv_usec) == -1) return NULL; tv.tv_usec = tv_usec; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 18:05:26 2012 From: python-checkins at python.org (benjamin.peterson) Date: Tue, 11 Sep 2012 18:05:26 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <3XGWDk0RdGzQb3@mail.python.org> http://hg.python.org/cpython/rev/8042b87bb762 changeset: 78995:8042b87bb762 parent: 78994:6cdc72f4d82c parent: 78993:59ec0b9ff724 user: Benjamin Peterson date: Tue Sep 11 12:05:18 2012 -0400 summary: merge heads files: Python/structmember.c | 6 +----- 1 files changed, 1 insertions(+), 5 deletions(-) diff --git a/Python/structmember.c b/Python/structmember.c --- a/Python/structmember.c +++ b/Python/structmember.c @@ -254,12 +254,8 @@ char *string; Py_ssize_t len; - if (!PyUnicode_Check(v)) { - PyErr_BadArgument(); - return -1; - } string = _PyUnicode_AsStringAndSize(v, &len); - if (len != 1) { + if (string == NULL || len != 1) { PyErr_BadArgument(); return -1; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 19:02:27 2012 From: python-checkins at python.org (r.david.murray) Date: Tue, 11 Sep 2012 19:02:27 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE0NjE3OiBjbGFy?= =?utf-8?q?ify_discussion_of_interrelationship_of_=5F=5Feq=5F=5F_and_=5F?= =?utf-8?b?X2hhc2hfXy4=?= Message-ID: <3XGXVW5l5NzQSX@mail.python.org> http://hg.python.org/cpython/rev/957e1eef3296 changeset: 78996:957e1eef3296 branch: 3.2 parent: 78992:afe55cd04119 user: R David Murray date: Tue Sep 11 13:01:43 2012 -0400 summary: #14617: clarify discussion of interrelationship of __eq__ and __hash__. files: Doc/reference/datamodel.rst | 26 ++++++++++++------------ 1 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1255,22 +1255,22 @@ by default; with them, all objects compare unequal (except with themselves) and ``x.__hash__()`` returns ``id(x)``. - Classes which inherit a :meth:`__hash__` method from a parent class but - change the meaning of :meth:`__eq__` such that the hash value returned is no - longer appropriate (e.g. by switching to a value-based concept of equality - instead of the default identity based equality) can explicitly flag - themselves as being unhashable by setting ``__hash__ = None`` in the class - definition. Doing so means that not only will instances of the class raise an - appropriate :exc:`TypeError` when a program attempts to retrieve their hash - value, but they will also be correctly identified as unhashable when checking - ``isinstance(obj, collections.Hashable)`` (unlike classes which define their - own :meth:`__hash__` to explicitly raise :exc:`TypeError`). + A class that overrides :meth:`__eq__` and does not define :meth:`__hash__` + will have its :meth:`__hash__` implicitly set to ``None``. When the + :meth:`__hash__` method of a class is ``None``, instances of the class will + raise an appropriate :exc:`TypeError` when a program attempts to retrieve + their hash value, and will also be correctly identified as unhashable when + checking ``isinstance(obj, collections.Hashable``). If a class that overrides :meth:`__eq__` needs to retain the implementation of :meth:`__hash__` from a parent class, the interpreter must be told this - explicitly by setting ``__hash__ = .__hash__``. Otherwise the - inheritance of :meth:`__hash__` will be blocked, just as if :attr:`__hash__` - had been explicitly set to :const:`None`. + explicitly by setting ``__hash__ = .__hash__``. + + If a class that does not override :meth:`__eq__` wishes to suppress hash + support, it should include ``__hash__ = None`` in the class definition. + A class which defines its own :meth:`__hash__` that explicitly raises + a :exc:`TypeError` would be incorrectly identified as hashable by + an ``isinstance(obj, collections.Hashable)`` call. See also the :option:`-R` command-line option. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 19:02:29 2012 From: python-checkins at python.org (r.david.murray) Date: Tue, 11 Sep 2012 19:02:29 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Merge_=2314617=3A_clarify_discussion_of_interrelationshi?= =?utf-8?b?cCBvZiBfX2VxX18gYW5kIF9faGFzaF9fLg==?= Message-ID: <3XGXVY29dHzQNy@mail.python.org> http://hg.python.org/cpython/rev/c8d60d0c736b changeset: 78997:c8d60d0c736b parent: 78995:8042b87bb762 parent: 78996:957e1eef3296 user: R David Murray date: Tue Sep 11 13:02:13 2012 -0400 summary: Merge #14617: clarify discussion of interrelationship of __eq__ and __hash__. files: Doc/reference/datamodel.rst | 26 ++++++++++++------------ 1 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1271,22 +1271,22 @@ and ``x.__hash__()`` returns an appropriate value such that ``x == y`` implies both that ``x is y`` and ``hash(x) == hash(y)``. - Classes which inherit a :meth:`__hash__` method from a parent class but - change the meaning of :meth:`__eq__` such that the hash value returned is no - longer appropriate (e.g. by switching to a value-based concept of equality - instead of the default identity based equality) can explicitly flag - themselves as being unhashable by setting ``__hash__ = None`` in the class - definition. Doing so means that not only will instances of the class raise an - appropriate :exc:`TypeError` when a program attempts to retrieve their hash - value, but they will also be correctly identified as unhashable when checking - ``isinstance(obj, collections.Hashable)`` (unlike classes which define their - own :meth:`__hash__` to explicitly raise :exc:`TypeError`). + A class that overrides :meth:`__eq__` and does not define :meth:`__hash__` + will have its :meth:`__hash__` implicitly set to ``None``. When the + :meth:`__hash__` method of a class is ``None``, instances of the class will + raise an appropriate :exc:`TypeError` when a program attempts to retrieve + their hash value, and will also be correctly identified as unhashable when + checking ``isinstance(obj, collections.Hashable``). If a class that overrides :meth:`__eq__` needs to retain the implementation of :meth:`__hash__` from a parent class, the interpreter must be told this - explicitly by setting ``__hash__ = .__hash__``. Otherwise the - inheritance of :meth:`__hash__` will be blocked, just as if :attr:`__hash__` - had been explicitly set to :const:`None`. + explicitly by setting ``__hash__ = .__hash__``. + + If a class that does not override :meth:`__eq__` wishes to suppress hash + support, it should include ``__hash__ = None`` in the class definition. + A class which defines its own :meth:`__hash__` that explicitly raises + a :exc:`TypeError` would be incorrectly identified as hashable by + an ``isinstance(obj, collections.Hashable)`` call. .. note:: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Sep 11 19:28:53 2012 From: python-checkins at python.org (christian.heimes) Date: Tue, 11 Sep 2012 19:28:53 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Updates_NEWS_for_issue_=23?= =?utf-8?q?15895?= Message-ID: <3XGY511gdDzQ7Z@mail.python.org> http://hg.python.org/cpython/rev/6fea947edead changeset: 78998:6fea947edead user: Christian Heimes date: Tue Sep 11 19:28:42 2012 +0200 summary: Updates NEWS for issue #15895 files: Misc/NEWS | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -11,8 +11,8 @@ ----------------- - Issue #15895: Fix FILE pointer leak in one error branch of - PyRun_SimpleFileExFlags() when - filename points to a pyc/pyo file and closeit is false. + PyRun_SimpleFileExFlags() when filename points to a pyc/pyo file, closeit + is false an and set_main_loader() fails. - Issue #15900: Fix reference leak in PyUnicode_TranslateCharmap(). -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Wed Sep 12 06:02:22 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 12 Sep 2012 06:02:22 +0200 Subject: [Python-checkins] Daily reference leaks (6fea947edead): sum=0 Message-ID: results for 6fea947edead on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogEvFzzU', '-x'] From python-checkins at python.org Wed Sep 12 06:12:44 2012 From: python-checkins at python.org (barry.warsaw) Date: Wed, 12 Sep 2012 06:12:44 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogLSBJc3N1ZSAjMTU5?= =?utf-8?q?06=3A_Fix_a_regression_in_argparse_caused_by_the_preceding_chan?= =?utf-8?b?Z2Us?= Message-ID: <3XGqMw3YzRzQb1@mail.python.org> http://hg.python.org/cpython/rev/739606bdcba4 changeset: 78999:739606bdcba4 branch: 2.7 parent: 78982:706115cb2cdb user: Barry Warsaw date: Tue Sep 11 21:06:29 2012 -0400 summary: - Issue #15906: Fix a regression in argparse caused by the preceding change, when action='append', type='str' and default=[]. files: Lib/argparse.py | 1 + Lib/test/test_argparse.py | 10 ++++++++++ Misc/NEWS | 3 +++ 3 files changed, 14 insertions(+), 0 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1948,6 +1948,7 @@ # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and + isinstance(action, _StoreAction) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest, diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4480,6 +4480,16 @@ args = parser.parse_args([]) self.assertEqual(NS(foo='foo_converted'), args) + def test_issue_15906(self): + # Issue #15906: When action='append', type=str, default=[] are + # providing, the dest value was the string representation "[]" when it + # should have been an empty list. + parser = argparse.ArgumentParser() + parser.add_argument('--test', dest='test', type=str, + default=[], action='append') + args = parser.parse_args([]) + self.assertEqual(args.test, []) + # ====================== # parse_known_args tests # ====================== diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -119,6 +119,9 @@ especially problematic for the FileType type, as a default file would always be opened, even if a file argument was specified on the command line. +- Issue #15906: Fix a regression in argparse caused by the preceding change, + when action='append', type='str' and default=[]. + - Issue #13370: Ensure that ctypes works on Mac OS X when Python is compiled using the clang compiler -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 06:13:16 2012 From: python-checkins at python.org (barry.warsaw) Date: Wed, 12 Sep 2012 06:13:16 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogLSBJc3N1ZSAjMTU5?= =?utf-8?q?06=3A_Fix_a_regression_in_argparse_caused_by_the_preceding_chan?= =?utf-8?b?Z2Us?= Message-ID: <3XGqNX0SYJzQZq@mail.python.org> http://hg.python.org/cpython/rev/bc342cd7ed96 changeset: 79000:bc342cd7ed96 branch: 3.2 parent: 78996:957e1eef3296 user: Barry Warsaw date: Tue Sep 11 22:38:47 2012 -0400 summary: - Issue #15906: Fix a regression in argparse caused by the preceding change, when action='append', type='str' and default=[]. files: Lib/argparse.py | 1 + Lib/test/test_argparse.py | 10 ++++++++++ Misc/NEWS | 3 +++ 3 files changed, 14 insertions(+), 0 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1957,6 +1957,7 @@ # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and + isinstance(action, _StoreAction) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest, diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4516,6 +4516,16 @@ args = parser.parse_args([]) self.assertEqual(NS(foo='foo_converted'), args) + def test_issue_15906(self): + # Issue #15906: When action='append', type=str, default=[] are + # providing, the dest value was the string representation "[]" when it + # should have been an empty list. + parser = argparse.ArgumentParser() + parser.add_argument('--test', dest='test', type=str, + default=[], action='append') + args = parser.parse_args([]) + self.assertEqual(args.test, []) + # ====================== # parse_known_args tests # ====================== diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -139,6 +139,9 @@ especially problematic for the FileType type, as a default file would always be opened, even if a file argument was specified on the command line. +- Issue #15906: Fix a regression in argparse caused by the preceding change, + when action='append', type='str' and default=[]. + - Issue #13370: Ensure that ctypes works on Mac OS X when Python is compiled using the clang compiler -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 06:13:47 2012 From: python-checkins at python.org (barry.warsaw) Date: Wed, 12 Sep 2012 06:13:47 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_-_Issue_=2315906=3A_Fix_a_regression_in_argparse_caused_?= =?utf-8?q?by_the_preceding_change=2C?= Message-ID: <3XGqP73SvPzML8@mail.python.org> http://hg.python.org/cpython/rev/25e41fdc4e60 changeset: 79001:25e41fdc4e60 parent: 78998:6fea947edead parent: 79000:bc342cd7ed96 user: Barry Warsaw date: Wed Sep 12 00:12:29 2012 -0400 summary: - Issue #15906: Fix a regression in argparse caused by the preceding change, when action='append', type='str' and default=[]. files: Lib/argparse.py | 1 + Lib/test/test_argparse.py | 10 ++++++++++ Misc/NEWS | 3 +++ 3 files changed, 14 insertions(+), 0 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1961,6 +1961,7 @@ # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and + isinstance(action, _StoreAction) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest, diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4607,6 +4607,16 @@ args = parser.parse_args([]) self.assertEqual(NS(foo='foo_converted'), args) + def test_issue_15906(self): + # Issue #15906: When action='append', type=str, default=[] are + # providing, the dest value was the string representation "[]" when it + # should have been an empty list. + parser = argparse.ArgumentParser() + parser.add_argument('--test', dest='test', type=str, + default=[], action='append') + args = parser.parse_args([]) + self.assertEqual(args.test, []) + # ====================== # parse_known_args tests # ====================== diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -56,6 +56,9 @@ especially problematic for the FileType type, as a default file would always be opened, even if a file argument was specified on the command line. +- Issue #15906: Fix a regression in argparse caused by the preceding change, + when action='append', type='str' and default=[]. + Extension Modules ----------------- -- Repository URL: http://hg.python.org/cpython From chris.jerdonek at gmail.com Wed Sep 12 06:30:57 2012 From: chris.jerdonek at gmail.com (Chris Jerdonek) Date: Tue, 11 Sep 2012 21:30:57 -0700 Subject: [Python-checkins] cpython (merge 3.2 -> default): - Issue #15906: Fix a regression in argparse caused by the preceding change, In-Reply-To: <3XGqP73SvPzML8@mail.python.org> References: <3XGqP73SvPzML8@mail.python.org> Message-ID: On Tue, Sep 11, 2012 at 9:13 PM, barry.warsaw wrote: > http://hg.python.org/cpython/rev/25e41fdc4e60 > changeset: 79001:25e41fdc4e60 > parent: 78998:6fea947edead > parent: 79000:bc342cd7ed96 > user: Barry Warsaw > date: Wed Sep 12 00:12:29 2012 -0400 > summary: > - Issue #15906: Fix a regression in argparse caused by the preceding change, > when action='append', type='str' and default=[]. I didn't have time to respond Barry's e-mail from four hours ago before this was committed. I think this change may be problematic. At the least, I think people should have an opportunity to air their specific concerns and talk through the implications. Also, from the discussion it seemed like the sentiment was leaning towards a different approach for the fix. I made a comment on the issue with some more extended remarks: http://bugs.python.org/msg170351 --Chris > > files: > Lib/argparse.py | 1 + > Lib/test/test_argparse.py | 10 ++++++++++ > Misc/NEWS | 3 +++ > 3 files changed, 14 insertions(+), 0 deletions(-) > > > diff --git a/Lib/argparse.py b/Lib/argparse.py > --- a/Lib/argparse.py > +++ b/Lib/argparse.py > @@ -1961,6 +1961,7 @@ > # twice (which may fail) if the argument was given, but > # only if it was defined already in the namespace > if (action.default is not None and > + isinstance(action, _StoreAction) and > hasattr(namespace, action.dest) and > action.default is getattr(namespace, action.dest)): > setattr(namespace, action.dest, > diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py > --- a/Lib/test/test_argparse.py > +++ b/Lib/test/test_argparse.py > @@ -4607,6 +4607,16 @@ > args = parser.parse_args([]) > self.assertEqual(NS(foo='foo_converted'), args) > > + def test_issue_15906(self): > + # Issue #15906: When action='append', type=str, default=[] are > + # providing, the dest value was the string representation "[]" when it > + # should have been an empty list. > + parser = argparse.ArgumentParser() > + parser.add_argument('--test', dest='test', type=str, > + default=[], action='append') > + args = parser.parse_args([]) > + self.assertEqual(args.test, []) > + > # ====================== > # parse_known_args tests > # ====================== > diff --git a/Misc/NEWS b/Misc/NEWS > --- a/Misc/NEWS > +++ b/Misc/NEWS > @@ -56,6 +56,9 @@ > especially problematic for the FileType type, as a default file would always > be opened, even if a file argument was specified on the command line. > > +- Issue #15906: Fix a regression in argparse caused by the preceding change, > + when action='append', type='str' and default=[]. > + > Extension Modules > ----------------- > > > -- > Repository URL: http://hg.python.org/cpython > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From python-checkins at python.org Wed Sep 12 07:17:22 2012 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 12 Sep 2012 07:17:22 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogRml4IGlzc3VlICMx?= =?utf-8?q?5899_-__howto/unicode=2Erst_doctest_corrections_for_2=2E7_branc?= =?utf-8?q?h=2E?= Message-ID: <3XGrpV3qKmzQYt@mail.python.org> http://hg.python.org/cpython/rev/142fbadd0ae1 changeset: 79002:142fbadd0ae1 branch: 2.7 parent: 78982:706115cb2cdb user: Senthil Kumaran date: Tue Sep 11 22:14:23 2012 -0700 summary: Fix issue #15899 - howto/unicode.rst doctest corrections for 2.7 branch. files: Doc/howto/unicode.rst | 32 ++++++++++++++++-------------- 1 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -253,11 +253,11 @@ >>> s = unicode('abcdef') >>> type(s) - >>> unicode('abcdef' + chr(255)) + >>> unicode('abcdef' + chr(255)) #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? + ... UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6: - ordinal not in range(128) + ordinal not in range(128) The ``errors`` argument specifies the response when the input string can't be converted according to the encoding's rules. Legal values for this argument are @@ -265,11 +265,11 @@ 'REPLACEMENT CHARACTER'), or 'ignore' (just leave the character out of the Unicode result). The following examples show the differences:: - >>> unicode('\x80abc', errors='strict') + >>> unicode('\x80abc', errors='strict') #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? + ... UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: - ordinal not in range(128) + ordinal not in range(128) >>> unicode('\x80abc', errors='replace') u'\ufffdabc' >>> unicode('\x80abc', errors='ignore') @@ -312,10 +312,11 @@ operation; Python's default ASCII encoding will be used, so characters greater than 127 will cause an exception:: - >>> s.find('Was\x9f') + >>> s.find('Was\x9f') #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? - UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3: ordinal not in range(128) + ... + UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3: + ordinal not in range(128) >>> s.find(u'Was\x9f') -1 @@ -333,10 +334,11 @@ >>> u = unichr(40960) + u'abcd' + unichr(1972) >>> u.encode('utf-8') '\xea\x80\x80abcd\xde\xb4' - >>> u.encode('ascii') + >>> u.encode('ascii') #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? - UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in position 0: ordinal not in range(128) + ... + UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in + position 0: ordinal not in range(128) >>> u.encode('ascii', 'ignore') 'abcd' >>> u.encode('ascii', 'replace') @@ -384,9 +386,9 @@ :: >>> s = u"a\xac\u1234\u20ac\U00008000" - ^^^^ two-digit hex escape - ^^^^^^ four-digit Unicode escape - ^^^^^^^^^^ eight-digit Unicode escape + ... # ^^^^ two-digit hex escape + ... # ^^^^^^ four-digit Unicode escape + ... # ^^^^^^^^^^ eight-digit Unicode escape >>> for c in s: print ord(c), ... 97 172 4660 8364 32768 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 07:17:53 2012 From: python-checkins at python.org (senthil.kumaran) Date: Wed, 12 Sep 2012 07:17:53 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_Automated_merge_with_file=3A///home/vagrant/3=2E2?= Message-ID: <3XGrq56pZvzQQk@mail.python.org> http://hg.python.org/cpython/rev/befd752a3218 changeset: 79003:befd752a3218 branch: 2.7 parent: 78999:739606bdcba4 parent: 79002:142fbadd0ae1 user: Senthil Kumaran date: Tue Sep 11 22:16:58 2012 -0700 summary: Automated merge with file:///home/vagrant/3.2 files: Doc/howto/unicode.rst | 32 ++++++++++++++++-------------- 1 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Doc/howto/unicode.rst b/Doc/howto/unicode.rst --- a/Doc/howto/unicode.rst +++ b/Doc/howto/unicode.rst @@ -253,11 +253,11 @@ >>> s = unicode('abcdef') >>> type(s) - >>> unicode('abcdef' + chr(255)) + >>> unicode('abcdef' + chr(255)) #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? + ... UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 6: - ordinal not in range(128) + ordinal not in range(128) The ``errors`` argument specifies the response when the input string can't be converted according to the encoding's rules. Legal values for this argument are @@ -265,11 +265,11 @@ 'REPLACEMENT CHARACTER'), or 'ignore' (just leave the character out of the Unicode result). The following examples show the differences:: - >>> unicode('\x80abc', errors='strict') + >>> unicode('\x80abc', errors='strict') #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? + ... UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: - ordinal not in range(128) + ordinal not in range(128) >>> unicode('\x80abc', errors='replace') u'\ufffdabc' >>> unicode('\x80abc', errors='ignore') @@ -312,10 +312,11 @@ operation; Python's default ASCII encoding will be used, so characters greater than 127 will cause an exception:: - >>> s.find('Was\x9f') + >>> s.find('Was\x9f') #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? - UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3: ordinal not in range(128) + ... + UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3: + ordinal not in range(128) >>> s.find(u'Was\x9f') -1 @@ -333,10 +334,11 @@ >>> u = unichr(40960) + u'abcd' + unichr(1972) >>> u.encode('utf-8') '\xea\x80\x80abcd\xde\xb4' - >>> u.encode('ascii') + >>> u.encode('ascii') #doctest: +NORMALIZE_WHITESPACE Traceback (most recent call last): - File "", line 1, in ? - UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in position 0: ordinal not in range(128) + ... + UnicodeEncodeError: 'ascii' codec can't encode character u'\ua000' in + position 0: ordinal not in range(128) >>> u.encode('ascii', 'ignore') 'abcd' >>> u.encode('ascii', 'replace') @@ -384,9 +386,9 @@ :: >>> s = u"a\xac\u1234\u20ac\U00008000" - ^^^^ two-digit hex escape - ^^^^^^ four-digit Unicode escape - ^^^^^^^^^^ eight-digit Unicode escape + ... # ^^^^ two-digit hex escape + ... # ^^^^^^ four-digit Unicode escape + ... # ^^^^^^^^^^ eight-digit Unicode escape >>> for c in s: print ord(c), ... 97 172 4660 8364 32768 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 15:32:51 2012 From: python-checkins at python.org (christian.heimes) Date: Wed, 12 Sep 2012 15:32:51 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fix_out_of_bou?= =?utf-8?q?nds_read_in_long=5Fnew=28=29_for_empty_bytes_with_an_explicit_b?= =?utf-8?q?ase=2E?= Message-ID: <3XH3pC3dN3zQdg@mail.python.org> http://hg.python.org/cpython/rev/3d5db784821f changeset: 79004:3d5db784821f branch: 3.2 parent: 79000:bc342cd7ed96 user: Christian Heimes date: Wed Sep 12 15:31:43 2012 +0200 summary: Fix out of bounds read in long_new() for empty bytes with an explicit base. int(b'', somebase) calls PyLong_FromString() with char* of length 1 but the function accesses the first argument at offset 1. CID 715359 files: Objects/longobject.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4149,8 +4149,8 @@ string = PyByteArray_AS_STRING(x); else string = PyBytes_AS_STRING(x); - if (strlen(string) != (size_t)size) { - /* We only see this if there's a null byte in x, + if (strlen(string) != (size_t)size || !size) { + /* We only see this if there's a null byte in x or x is empty, x is a bytes or buffer, *and* a base is given. */ PyErr_Format(PyExc_ValueError, "invalid literal for int() with base %d: %R", -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 15:33:23 2012 From: python-checkins at python.org (christian.heimes) Date: Wed, 12 Sep 2012 15:33:23 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Fix_out_of_bounds_read_in_long=5Fnew=28=29_for_empty_byt?= =?utf-8?q?es_with_an_explicit_base=2E?= Message-ID: <3XH3pq1Xy6zQbQ@mail.python.org> http://hg.python.org/cpython/rev/2fa7c104f909 changeset: 79005:2fa7c104f909 parent: 79001:25e41fdc4e60 parent: 79004:3d5db784821f user: Christian Heimes date: Wed Sep 12 15:32:06 2012 +0200 summary: Fix out of bounds read in long_new() for empty bytes with an explicit base. int(b'', somebase) calls PyLong_FromString() with char* of length 1 but the function accesses the first argument at offset 1. CID 715359 files: Objects/longobject.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Objects/longobject.c b/Objects/longobject.c --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -4285,8 +4285,8 @@ string = PyByteArray_AS_STRING(x); else string = PyBytes_AS_STRING(x); - if (strlen(string) != (size_t)size) { - /* We only see this if there's a null byte in x, + if (strlen(string) != (size_t)size || !size) { + /* We only see this if there's a null byte in x or x is empty, x is a bytes or buffer, *and* a base is given. */ PyErr_Format(PyExc_ValueError, "invalid literal for int() with base %d: %R", -- Repository URL: http://hg.python.org/cpython From barry at python.org Wed Sep 12 16:06:35 2012 From: barry at python.org (Barry Warsaw) Date: Wed, 12 Sep 2012 10:06:35 -0400 Subject: [Python-checkins] [Python-Dev] cpython (merge 3.2 -> default): - Issue #15906: Fix a regression in argparse caused by the preceding change, In-Reply-To: References: <3XGqP73SvPzML8@mail.python.org> Message-ID: <20120912100635.5ad0fe45@limelight.wooz.org> On Sep 11, 2012, at 09:30 PM, Chris Jerdonek wrote: >I didn't have time to respond Barry's e-mail from four hours ago >before this was committed. I think this change may be problematic. >At the least, I think people should have an opportunity to air their >specific concerns and talk through the implications. > >Also, from the discussion it seemed like the sentiment was leaning >towards a different approach for the fix. > >I made a comment on the issue with some more extended remarks: > >http://bugs.python.org/msg170351 The alternative suggested fix breaks the test suite (yes I tried it). So maybe we have to go back and decide whether the original fix for #12776 and #11839 is correct. More detail in the tracker issue. -Barry From stefan at bytereef.org Wed Sep 12 16:00:03 2012 From: stefan at bytereef.org (Stefan Krah) Date: Wed, 12 Sep 2012 16:00:03 +0200 Subject: [Python-checkins] cpython (merge 3.2 -> default): Fix out of bounds read in long_new() for empty bytes with an explicit base. In-Reply-To: <3XH3pq1Xy6zQbQ@mail.python.org> References: <3XH3pq1Xy6zQbQ@mail.python.org> Message-ID: <20120912140003.GA29860@sleipnir.bytereef.org> christian.heimes wrote: > Fix out of bounds read in long_new() for empty bytes with an explicit base. int(b'', somebase) calls PyLong_FromString() with char* of length 1 but the function accesses the first argument at offset 1. CID 715359 > > files: > Objects/longobject.c | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > > > diff --git a/Objects/longobject.c b/Objects/longobject.c > --- a/Objects/longobject.c > +++ b/Objects/longobject.c > @@ -4285,8 +4285,8 @@ > string = PyByteArray_AS_STRING(x); > else > string = PyBytes_AS_STRING(x); > - if (strlen(string) != (size_t)size) { > - /* We only see this if there's a null byte in x, > + if (strlen(string) != (size_t)size || !size) { > + /* We only see this if there's a null byte in x or x is empty, > x is a bytes or buffer, *and* a base is given. */ > PyErr_Format(PyExc_ValueError, > "invalid literal for int() with base %d: %R", This is a false positive: Assumption: string == "" Call: PyLong_FromString("", NULL, (int)base); Now: str == "" Coverity claims an invalid access at str[1]: if (str[0] == '0' && ((base == 16 && (str[1] == 'x' || str[1] == 'X')) || (base == 8 && (str[1] == 'o' || str[1] == 'O')) || (base == 2 && (str[1] == 'b' || str[1] == 'B')))) But str[1] is never accessed due to shortcut evaluation. Coverity appears to have serious problems with shortcut evaluations in many places. Stefan Krah From python-checkins at python.org Wed Sep 12 17:54:06 2012 From: python-checkins at python.org (christian.heimes) Date: Wed, 12 Sep 2012 17:54:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Partly_revert_?= =?utf-8?q?ad3824a90261_and_add_comment_about_reference_ownership?= Message-ID: <3XH6xB6s3RzQY5@mail.python.org> http://hg.python.org/cpython/rev/2888356cdd4e changeset: 79006:2888356cdd4e branch: 3.2 parent: 79004:3d5db784821f user: Christian Heimes date: Wed Sep 12 17:52:46 2012 +0200 summary: Partly revert ad3824a90261 and add comment about reference ownership files: Python/symtable.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -37,7 +37,7 @@ if (ste == NULL) goto fail; ste->ste_table = st; - ste->ste_id = k; + ste->ste_id = k; /* ste owns reference to k */ ste->ste_name = name; Py_INCREF(name); @@ -83,7 +83,6 @@ return ste; fail: - Py_XDECREF(k); Py_XDECREF(ste); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 17:54:08 2012 From: python-checkins at python.org (christian.heimes) Date: Wed, 12 Sep 2012 17:54:08 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Partly_revert_ad3824a90261_and_add_comment_about_referen?= =?utf-8?q?ce_ownership?= Message-ID: <3XH6xD2Z0xzQZQ@mail.python.org> http://hg.python.org/cpython/rev/c1b950541e46 changeset: 79007:c1b950541e46 parent: 79005:2fa7c104f909 parent: 79006:2888356cdd4e user: Christian Heimes date: Wed Sep 12 17:53:15 2012 +0200 summary: Partly revert ad3824a90261 and add comment about reference ownership files: Python/symtable.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -33,7 +33,7 @@ if (ste == NULL) goto fail; ste->ste_table = st; - ste->ste_id = k; + ste->ste_id = k; /* ste owns reference to k */ ste->ste_name = name; Py_INCREF(name); @@ -79,7 +79,6 @@ return ste; fail: - Py_XDECREF(k); Py_XDECREF(ste); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 17:54:09 2012 From: python-checkins at python.org (christian.heimes) Date: Wed, 12 Sep 2012 17:54:09 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Partly_revert_?= =?utf-8?q?ad3824a90261_and_add_comment_about_reference_ownership?= Message-ID: <3XH6xF5N0WzQZg@mail.python.org> http://hg.python.org/cpython/rev/f19b84915c17 changeset: 79008:f19b84915c17 branch: 2.7 parent: 79003:befd752a3218 user: Christian Heimes date: Wed Sep 12 17:52:46 2012 +0200 summary: Partly revert ad3824a90261 and add comment about reference ownership files: Python/symtable.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -31,7 +31,7 @@ if (ste == NULL) goto fail; ste->ste_table = st; - ste->ste_id = k; + ste->ste_id = k; /* ste owns reference to k */ ste->ste_name = name; Py_INCREF(name); @@ -75,7 +75,6 @@ return ste; fail: - Py_XDECREF(k); Py_XDECREF(ste); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 17:59:09 2012 From: python-checkins at python.org (christian.heimes) Date: Wed, 12 Sep 2012 17:59:09 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogQ2xlYW51cCAnaycg?= =?utf-8?q?when_the_creation_of_PySTEntryObject_fails=2E_ad3824a90261_used?= =?utf-8?q?_to?= Message-ID: <3XH7315TZ7zM20@mail.python.org> http://hg.python.org/cpython/rev/99ab7006e466 changeset: 79009:99ab7006e466 branch: 3.2 parent: 79006:2888356cdd4e user: Christian Heimes date: Wed Sep 12 17:58:10 2012 +0200 summary: Cleanup 'k' when the creation of PySTEntryObject fails. ad3824a90261 used to decref 'k' in too many error cases. files: Python/symtable.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -34,8 +34,10 @@ if (k == NULL) goto fail; ste = PyObject_New(PySTEntryObject, &PySTEntry_Type); - if (ste == NULL) + if (ste == NULL) { + Py_DECREF(k); goto fail; + } ste->ste_table = st; ste->ste_id = k; /* ste owns reference to k */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 17:59:11 2012 From: python-checkins at python.org (christian.heimes) Date: Wed, 12 Sep 2012 17:59:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Cleanup_=27k=27_when_the_creation_of_PySTEntryObject_fai?= =?utf-8?q?ls=2E_ad3824a90261_used_to?= Message-ID: <3XH7331w8czQY4@mail.python.org> http://hg.python.org/cpython/rev/5b64fefbc16b changeset: 79010:5b64fefbc16b parent: 79007:c1b950541e46 parent: 79009:99ab7006e466 user: Christian Heimes date: Wed Sep 12 17:58:20 2012 +0200 summary: Cleanup 'k' when the creation of PySTEntryObject fails. ad3824a90261 used to decref 'k' in too many error cases. files: Python/symtable.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -30,8 +30,10 @@ if (k == NULL) goto fail; ste = PyObject_New(PySTEntryObject, &PySTEntry_Type); - if (ste == NULL) + if (ste == NULL) { + Py_DECREF(k); goto fail; + } ste->ste_table = st; ste->ste_id = k; /* ste owns reference to k */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 17:59:12 2012 From: python-checkins at python.org (christian.heimes) Date: Wed, 12 Sep 2012 17:59:12 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogQ2xlYW51cCAnaycg?= =?utf-8?q?when_the_creation_of_PySTEntryObject_fails=2E_ad3824a90261_used?= =?utf-8?q?_to?= Message-ID: <3XH7344vjfzQbQ@mail.python.org> http://hg.python.org/cpython/rev/128fa8755e55 changeset: 79011:128fa8755e55 branch: 2.7 parent: 79008:f19b84915c17 user: Christian Heimes date: Wed Sep 12 17:58:10 2012 +0200 summary: Cleanup 'k' when the creation of PySTEntryObject fails. ad3824a90261 used to decref 'k' in too many error cases. files: Python/symtable.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -28,8 +28,10 @@ if (k == NULL) goto fail; ste = PyObject_New(PySTEntryObject, &PySTEntry_Type); - if (ste == NULL) + if (ste == NULL) { + Py_DECREF(k); goto fail; + } ste->ste_table = st; ste->ste_id = k; /* ste owns reference to k */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 18:02:46 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 12 Sep 2012 18:02:46 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315926=3A_Fix_cras?= =?utf-8?q?h_after_multiple_reinitializations_of_the_interpreter=2E?= Message-ID: <3XH77B1Ft4zQYl@mail.python.org> http://hg.python.org/cpython/rev/8d22d9528164 changeset: 79012:8d22d9528164 parent: 79005:2fa7c104f909 user: Antoine Pitrou date: Wed Sep 12 18:01:36 2012 +0200 summary: Issue #15926: Fix crash after multiple reinitializations of the interpreter. files: Misc/NEWS | 2 ++ Modules/posixmodule.c | 2 +- 2 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Core and Builtins ----------------- +- Issue #15926: Fix crash after multiple reinitializations of the interpreter. + - Issue #15895: Fix FILE pointer leak in one error branch of PyRun_SimpleFileExFlags() when filename points to a pyc/pyo file, closeit is false an and set_main_loader() fails. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -11852,7 +11852,6 @@ /* initialize TerminalSize_info */ PyStructSequence_InitType(&TerminalSizeType, &TerminalSize_desc); - Py_INCREF(&TerminalSizeType); } #if defined(HAVE_WAITID) && !defined(__APPLE__) Py_INCREF((PyObject*) &WaitidResultType); @@ -11915,6 +11914,7 @@ #endif /* __APPLE__ */ + Py_INCREF(&TerminalSizeType); PyModule_AddObject(m, "terminal_size", (PyObject*) &TerminalSizeType); billion = PyLong_FromLong(1000000000); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 18:02:47 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 12 Sep 2012 18:02:47 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Merge?= Message-ID: <3XH77C4N0TzQc1@mail.python.org> http://hg.python.org/cpython/rev/0191dd144be5 changeset: 79013:0191dd144be5 parent: 79012:8d22d9528164 parent: 79010:5b64fefbc16b user: Antoine Pitrou date: Wed Sep 12 18:02:18 2012 +0200 summary: Merge files: Python/symtable.c | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -30,10 +30,12 @@ if (k == NULL) goto fail; ste = PyObject_New(PySTEntryObject, &PySTEntry_Type); - if (ste == NULL) + if (ste == NULL) { + Py_DECREF(k); goto fail; + } ste->ste_table = st; - ste->ste_id = k; + ste->ste_id = k; /* ste owns reference to k */ ste->ste_name = name; Py_INCREF(name); @@ -79,7 +81,6 @@ return ste; fail: - Py_XDECREF(k); Py_XDECREF(ste); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 21:31:54 2012 From: python-checkins at python.org (barry.warsaw) Date: Wed, 12 Sep 2012 21:31:54 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_A_follow_up_fo?= =?utf-8?q?r_issue_=2315906=3A_change_the_test_for_calling_the_type_conver?= =?utf-8?q?sion?= Message-ID: <3XHCmV6wxJzQYl@mail.python.org> http://hg.python.org/cpython/rev/8f847f66a49f changeset: 79014:8f847f66a49f branch: 2.7 parent: 79011:128fa8755e55 user: Barry Warsaw date: Wed Sep 12 14:34:50 2012 -0400 summary: A follow up for issue #15906: change the test for calling the type conversion on the action's default, reverting it back to previous behavior. Conversion is only done on string defaults. Add a test for this and another test that ensures such type conversions are only called once. files: Lib/argparse.py | 2 +- Lib/test/test_argparse.py | 33 ++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1948,7 +1948,7 @@ # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and - isinstance(action, _StoreAction) and + isinstance(action.default, basestring) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest, diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4464,11 +4464,11 @@ args = parser.parse_args('--foo spam!'.split()) self.assertEqual(NS(foo='foo_converted'), args) -# ================================================================ -# Check that the type function is called with a non-string default -# ================================================================ - -class TestTypeFunctionCallWithNonStringDefault(TestCase): +# ================================================================== +# Check semantics regarding the default argument and type conversion +# ================================================================== + +class TestTypeFunctionCalledOnDefault(TestCase): def test_type_function_call_with_non_string_default(self): def spam(int_to_convert): @@ -4478,8 +4478,31 @@ parser = argparse.ArgumentParser() parser.add_argument('--foo', type=spam, default=0) args = parser.parse_args([]) + # foo should *not* be converted because its default is not a string. + self.assertEqual(NS(foo=0), args) + + def test_type_function_call_with_string_default(self): + def spam(int_to_convert): + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default='0') + args = parser.parse_args([]) + # foo is converted because its default is a string. self.assertEqual(NS(foo='foo_converted'), args) + def test_no_double_type_conversion_of_default(self): + def extend(str_to_convert): + return str_to_convert + '*' + + parser = argparse.ArgumentParser() + parser.add_argument('--test', type=extend, default='*') + args = parser.parse_args([]) + # The test argument will be two stars, one coming from the default + # value and one coming from the type conversion being called exactly + # once. + self.assertEqual(NS(test='**'), args) + def test_issue_15906(self): # Issue #15906: When action='append', type=str, default=[] are # providing, the dest value was the string representation "[]" when it -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 21:31:56 2012 From: python-checkins at python.org (barry.warsaw) Date: Wed, 12 Sep 2012 21:31:56 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_A_follow_up_fo?= =?utf-8?q?r_issue_=2315906=3A_change_the_test_for_calling_the_type_conver?= =?utf-8?q?sion?= Message-ID: <3XHCmX4BdczQZq@mail.python.org> http://hg.python.org/cpython/rev/088b16bd6396 changeset: 79015:088b16bd6396 branch: 3.2 parent: 79009:99ab7006e466 user: Barry Warsaw date: Wed Sep 12 14:34:50 2012 -0400 summary: A follow up for issue #15906: change the test for calling the type conversion on the action's default, reverting it back to previous behavior. Conversion is only done on string defaults. Add a test for this and another test that ensures such type conversions are only called once. files: Lib/argparse.py | 2 +- Lib/test/test_argparse.py | 33 ++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1957,7 +1957,7 @@ # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and - isinstance(action, _StoreAction) and + isinstance(action.default, basestring) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest, diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4500,11 +4500,11 @@ args = parser.parse_args('--foo spam!'.split()) self.assertEqual(NS(foo='foo_converted'), args) -# ================================================================ -# Check that the type function is called with a non-string default -# ================================================================ - -class TestTypeFunctionCallWithNonStringDefault(TestCase): +# ================================================================== +# Check semantics regarding the default argument and type conversion +# ================================================================== + +class TestTypeFunctionCalledOnDefault(TestCase): def test_type_function_call_with_non_string_default(self): def spam(int_to_convert): @@ -4514,8 +4514,31 @@ parser = argparse.ArgumentParser() parser.add_argument('--foo', type=spam, default=0) args = parser.parse_args([]) + # foo should *not* be converted because its default is not a string. + self.assertEqual(NS(foo=0), args) + + def test_type_function_call_with_string_default(self): + def spam(int_to_convert): + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default='0') + args = parser.parse_args([]) + # foo is converted because its default is a string. self.assertEqual(NS(foo='foo_converted'), args) + def test_no_double_type_conversion_of_default(self): + def extend(str_to_convert): + return str_to_convert + '*' + + parser = argparse.ArgumentParser() + parser.add_argument('--test', type=extend, default='*') + args = parser.parse_args([]) + # The test argument will be two stars, one coming from the default + # value and one coming from the type conversion being called exactly + # once. + self.assertEqual(NS(test='**'), args) + def test_issue_15906(self): # Issue #15906: When action='append', type=str, default=[] are # providing, the dest value was the string representation "[]" when it -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 21:31:57 2012 From: python-checkins at python.org (barry.warsaw) Date: Wed, 12 Sep 2012 21:31:57 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Update_merge_f?= =?utf-8?q?rom_2=2E7=3A_s/basetring/str?= Message-ID: <3XHCmY75mfzQgC@mail.python.org> http://hg.python.org/cpython/rev/5c754e7559ff changeset: 79016:5c754e7559ff branch: 3.2 user: Barry Warsaw date: Wed Sep 12 14:42:34 2012 -0400 summary: Update merge from 2.7: s/basetring/str files: Lib/argparse.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1957,7 +1957,7 @@ # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and - isinstance(action.default, basestring) and + isinstance(action.default, str) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 21:31:59 2012 From: python-checkins at python.org (barry.warsaw) Date: Wed, 12 Sep 2012 21:31:59 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Merge_3=2E2_fix_updates_and_tests_for_issue_=2315906=2E?= Message-ID: <3XHCmb2rrhzQcm@mail.python.org> http://hg.python.org/cpython/rev/9ae9326cd79a changeset: 79017:9ae9326cd79a parent: 79013:0191dd144be5 parent: 79016:5c754e7559ff user: Barry Warsaw date: Wed Sep 12 15:31:38 2012 -0400 summary: Merge 3.2 fix updates and tests for issue #15906. files: Lib/argparse.py | 2 +- Lib/test/test_argparse.py | 33 ++++++++++++++++++++++---- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1961,7 +1961,7 @@ # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and - isinstance(action, _StoreAction) and + isinstance(action.default, str) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest, diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4591,11 +4591,11 @@ args = parser.parse_args('--foo spam!'.split()) self.assertEqual(NS(foo='foo_converted'), args) -# ================================================================ -# Check that the type function is called with a non-string default -# ================================================================ - -class TestTypeFunctionCallWithNonStringDefault(TestCase): +# ================================================================== +# Check semantics regarding the default argument and type conversion +# ================================================================== + +class TestTypeFunctionCalledOnDefault(TestCase): def test_type_function_call_with_non_string_default(self): def spam(int_to_convert): @@ -4605,8 +4605,31 @@ parser = argparse.ArgumentParser() parser.add_argument('--foo', type=spam, default=0) args = parser.parse_args([]) + # foo should *not* be converted because its default is not a string. + self.assertEqual(NS(foo=0), args) + + def test_type_function_call_with_string_default(self): + def spam(int_to_convert): + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default='0') + args = parser.parse_args([]) + # foo is converted because its default is a string. self.assertEqual(NS(foo='foo_converted'), args) + def test_no_double_type_conversion_of_default(self): + def extend(str_to_convert): + return str_to_convert + '*' + + parser = argparse.ArgumentParser() + parser.add_argument('--test', type=extend, default='*') + args = parser.parse_args([]) + # The test argument will be two stars, one coming from the default + # value and one coming from the type conversion being called exactly + # once. + self.assertEqual(NS(test='**'), args) + def test_issue_15906(self): # Issue #15906: When action='append', type=str, default=[] are # providing, the dest value was the string representation "[]" when it -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Sep 12 21:37:55 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 12 Sep 2012 21:37:55 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315599=3A_FreeBSD_?= =?utf-8?q?on_KVM_cannot_handle_a_very_low_switch_interval=2E?= Message-ID: <3XHCvR4YdZzQW3@mail.python.org> http://hg.python.org/cpython/rev/9b40d018e4cf changeset: 79018:9b40d018e4cf user: Stefan Krah date: Wed Sep 12 21:30:09 2012 +0200 summary: Issue #15599: FreeBSD on KVM cannot handle a very low switch interval. files: Lib/test/test_threaded_import.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_threaded_import.py b/Lib/test/test_threaded_import.py --- a/Lib/test/test_threaded_import.py +++ b/Lib/test/test_threaded_import.py @@ -225,9 +225,11 @@ @reap_threads def test_main(): old_switchinterval = None + # Issue #15599: FreeBSD/KVM cannot handle gil_interval == 1. + new_switchinterval = 0.00001 if 'freebsd' in sys.platform else 0.00000001 try: old_switchinterval = sys.getswitchinterval() - sys.setswitchinterval(0.00000001) + sys.setswitchinterval(new_switchinterval) except AttributeError: pass try: -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Sep 13 05:57:27 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 13 Sep 2012 05:57:27 +0200 Subject: [Python-checkins] Daily reference leaks (9b40d018e4cf): sum=0 Message-ID: results for 9b40d018e4cf on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogRSBmfj', '-x'] From python-checkins at python.org Thu Sep 13 18:28:18 2012 From: python-checkins at python.org (richard.oudkerk) Date: Thu, 13 Sep 2012 18:28:18 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315881=3A_Clarify_?= =?utf-8?q?comment_in_exit_function?= Message-ID: <3XHlfB6GngzQkH@mail.python.org> http://hg.python.org/cpython/rev/2b79b4848f44 changeset: 79019:2b79b4848f44 user: Richard Oudkerk date: Thu Sep 13 17:27:15 2012 +0100 summary: Issue #15881: Clarify comment in exit function files: Lib/multiprocessing/util.py | 19 +++++++++++-------- 1 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -290,14 +290,17 @@ if current_process() is not None: # We check if the current process is None here because if - # it's None, any call to ``active_children()`` will throw an - # AttributeError (active_children winds up trying to get - # attributes from util._current_process). This happens in a - # variety of shutdown circumstances that are not well-understood - # because module-scope variables are not apparently supposed to - # be destroyed until after this function is called. However, - # they are indeed destroyed before this function is called. See - # issues #9775 and #15881. Also related: #4106, #9205, and #9207. + # it's None, any call to ``active_children()`` will throw + # an AttributeError (active_children winds up trying to + # get attributes from util._current_process). One + # situation where this can happen is if someone has + # manipulated sys.modules, causing this module to be + # garbage collected. The destructor for the module type + # then replaces all values in the module dict with None. + # For instance, after setuptools runs a test it replaces + # sys.modules with a copy created earlier. See issues + # #9775 and #15881. Also related: #4106, #9205, and + # #9207. for p in active_children(): if p._daemonic: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 14 01:00:36 2012 From: python-checkins at python.org (ezio.melotti) Date: Fri, 14 Sep 2012 01:00:36 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE1NDM3LCAjMTU0?= =?utf-8?q?39=3A_merge_Doc/ACKS=2Etxt_with_Misc/ACKS_and_modify_Doc/about?= =?utf-8?q?=2Erst?= Message-ID: <3XHwLr547zzQjv@mail.python.org> http://hg.python.org/cpython/rev/76dd082d332e changeset: 79022:76dd082d332e branch: 2.7 parent: 79014:8f847f66a49f user: Ezio Melotti date: Fri Sep 14 01:58:33 2012 +0300 summary: #15437, #15439: merge Doc/ACKS.txt with Misc/ACKS and modify Doc/about.rst accordingly. files: Doc/ACKS.txt | 231 -------------------------------------- Doc/about.rst | 9 +- Misc/ACKS | 119 ++++++++++++++++++- 3 files changed, 122 insertions(+), 237 deletions(-) diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt deleted file mode 100644 --- a/Doc/ACKS.txt +++ /dev/null @@ -1,231 +0,0 @@ -Contributors to the Python Documentation ----------------------------------------- - -This section lists people who have contributed in some way to the Python -documentation. It is probably not complete -- if you feel that you or -anyone else should be on this list, please let us know (send email to -docs at python.org), and we'll be glad to correct the problem. - -.. acks:: - - * Aahz - * Michael Abbott - * Steve Alexander - * Jim Ahlstrom - * Fred Allen - * A. Amoroso - * Pehr Anderson - * Oliver Andrich - * Heidi Annexstad - * Jes?s Cea Avi?n - * Manuel Balsera - * Daniel Barclay - * Chris Barker - * Don Bashford - * Anthony Baxter - * Alexander Belopolsky - * Bennett Benson - * Jonathan Black - * Robin Boerdijk - * Michal Bozon - * Aaron Brancotti - * Georg Brandl - * Keith Briggs - * Ian Bruntlett - * Lee Busby - * Arnaud Calmettes - * Lorenzo M. Catucci - * Carl Cerecke - * Mauro Cicognini - * Gilles Civario - * Mike Clarkson - * Steve Clift - * Dave Cole - * Matthew Cowles - * Jeremy Craven - * Andrew Dalke - * Ben Darnell - * L. Peter Deutsch - * Robert Donohue - * Fred L. Drake, Jr. - * Josip Dzolonga - * Jeff Epler - * Michael Ernst - * Blame Andy Eskilsson - * Carey Evans - * Martijn Faassen - * Carl Feynman - * Dan Finnie - * Hern?n Mart?nez Foffani - * Stefan Franke - * Jim Fulton - * Peter Funk - * Lele Gaifax - * Matthew Gallagher - * Gabriel Genellina - * Ben Gertzfield - * Nadim Ghaznavi - * Jonathan Giddy - * Shelley Gooch - * Nathaniel Gray - * Grant Griffin - * Thomas Guettler - * Anders Hammarquist - * Mark Hammond - * Harald Hanche-Olsen - * Manus Hand - * Gerhard H?ring - * Travis B. Hartwell - * Tim Hatch - * Janko Hauser - * Ben Hayden - * Thomas Heller - * Bernhard Herzog - * Magnus L. Hetland - * Konrad Hinsen - * Stefan Hoffmeister - * Albert Hofkamp - * Gregor Hoffleit - * Steve Holden - * Thomas Holenstein - * Gerrit Holl - * Rob Hooft - * Brian Hooper - * Randall Hopper - * Mike Hoy - * Michael Hudson - * Eric Huss - * Jeremy Hylton - * Roger Irwin - * Jack Jansen - * Philip H. Jensen - * Pedro Diaz Jimenez - * Kent Johnson - * Lucas de Jonge - * Andreas Jung - * Robert Kern - * Jim Kerr - * Jan Kim - * Kamil Kisiel - * Greg Kochanski - * Guido Kollerie - * Peter A. Koren - * Daniel Kozan - * Andrew M. Kuchling - * Dave Kuhlman - * Erno Kuusela - * Ross Lagerwall - * Thomas Lamb - * Detlef Lannert - * Piers Lauder - * Glyph Lefkowitz - * Robert Lehmann - * Marc-Andr? Lemburg - * Ross Light - * Ulf A. Lindgren - * Everett Lipman - * Mirko Liss - * Martin von L?wis - * Fredrik Lundh - * Jeff MacDonald - * John Machin - * Andrew MacIntyre - * Vladimir Marangozov - * Vincent Marchetti - * Westley Mart?nez - * Laura Matson - * Daniel May - * Rebecca McCreary - * Doug Mennella - * Paolo Milani - * Skip Montanaro - * Paul Moore - * Ross Moore - * Sjoerd Mullender - * Dale Nagata - * Michal Nowikowski - * Steffen Daode Nurpmeso - * Ng Pheng Siong - * Koray Oner - * Tomas Oppelstrup - * Denis S. Otkidach - * Zooko O'Whielacronx - * Shriphani Palakodety - * William Park - * Joonas Paalasmaa - * Harri Pasanen - * Bo Peng - * Tim Peters - * Benjamin Peterson - * Christopher Petrilli - * Justin D. Pettit - * Chris Phoenix - * Fran?ois Pinard - * Paul Prescod - * Eric S. Raymond - * Edward K. Ream - * Terry J. Reedy - * Sean Reifschneider - * Bernhard Reiter - * Armin Rigo - * Wes Rishel - * Armin Ronacher - * Jim Roskind - * Guido van Rossum - * Donald Wallace Rouse II - * Mark Russell - * Nick Russo - * Chris Ryland - * Constantina S. - * Hugh Sasse - * Bob Savage - * Scott Schram - * Neil Schemenauer - * Barry Scott - * Joakim Sernbrant - * Justin Sheehy - * Charlie Shepherd - * Yue Shuaijie - * Michael Simcich - * Ionel Simionescu - * Michael Sloan - * Gregory P. Smith - * Roy Smith - * Clay Spence - * Nicholas Spies - * Tage Stabell-Kulo - * Frank Stajano - * Anthony Starks - * Greg Stein - * Peter Stoehr - * Mark Summerfield - * Reuben Sumner - * Kalle Svensson - * Jim Tittsler - * David Turner - * Sandro Tosi - * Ville Vainio - * Martijn Vries - * Charles G. Waldman - * Greg Ward - * Barry Warsaw - * Corran Webster - * Glyn Webster - * Bob Weiner - * Eddy Welbourne - * Jeff Wheeler - * Mats Wichmann - * Gerry Wiener - * Timothy Wild - * Paul Winkler - * Collin Winter - * Blake Winton - * Dan Wolfe - * Adam Woodbeck - * Steven Work - * Thomas Wouters - * Ka-Ping Yee - * Rory Yorke - * Moshe Zadka - * Milan Zamazal - * Cheng Zhang diff --git a/Doc/about.rst b/Doc/about.rst --- a/Doc/about.rst +++ b/Doc/about.rst @@ -29,8 +29,13 @@ See :ref:`reporting-bugs` for information how to report bugs in this documentation, or Python itself. -.. including the ACKS file here so that it can be maintained separately -.. include:: ACKS.txt + +Contributors to the Python Documentation +---------------------------------------- + +Many people have contributed to the Python language, the Python standard +library, and the Python documentation. See :source:`Misc/ACKS` in the Python +source distribution for a partial list of contributors. It is only with the input and contributions of the Python community that Python has such wonderful documentation -- Thank You! diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -11,25 +11,33 @@ PS: In the standard Python distribution, this file is encoded in UTF-8 and the list is in rough alphabetical order by last names. +Aahz +Michael Abbott David Abrahams Jim Ahlstrom Farhan Ahmad Nir Aides Yaniv Aknin Jyrki Alakuijala +Steve Alexander +Fred Allen Billy G. Allie Kevin Altis Joe Amenta +A. Amoroso Mark Anacker Anders Andersen John Anderson +Pehr Anderson Erik Anders?n Oliver Andrich Ross Andrus +Heidi Annexstad ?ric Araujo Jason Asbahr David Ascher Chris AtLee +Jes?s Cea Avi?n John Aycock Jan-Hein B?hrman Donovan Baarda @@ -41,8 +49,10 @@ Greg Ball Luigi Ballabio Jeff Balogh +Manuel Balsera Matt Bandy Michael J. Barber +Daniel Barclay Chris Barker Anton Barkovsky Nick Barnes @@ -51,6 +61,7 @@ Cesar Eduardo Barros Des Barry Ulf Bartelt +Don Bashford Nick Bastin Jeff Bauer Mike Bayer @@ -69,6 +80,7 @@ Alexander ?????? Belopolsky Andrew Bennetts Andy Bensky +Bennett Benson Michel Van den Bergh Eric Beser Steven Bethard @@ -80,6 +92,7 @@ Philippe Biondi Stuart Bishop Roy Bixler +Jonathan Black Mike Bland Martin Bless Pablo Bleyer @@ -88,6 +101,7 @@ Finn Bock Paul Boddie Matthew Boedicker +Robin Boerdijk David Bolen Gawain Bolton Gregory Bond @@ -96,13 +110,16 @@ Eric Bouck Thierry Bousch Sebastian Boving +Michal Bozon Jeff Bradberry +Aaron Brancotti Monty Brandenberg Georg Brandl Christopher Brannon Terrence Brannon Dave Brennan Tom Bridgman +Keith Briggs Richard Brodie Michael Broghton Daniel Brotsky @@ -111,6 +128,7 @@ Oleg Broytmann Dave Brueck Francisco Mart?n Brugu? +Ian Bruntlett Stan Bubrouski Erik de Bueger Dick Bulterman @@ -134,6 +152,7 @@ Donn Cave Charles Cazabon Per Cederqvist +Carl Cerecke Octavian Cerna Pascal Chambon John Chandler @@ -151,8 +170,10 @@ Anders Chrigstr?m Tom Christiansen Vadim Chugunov +Mauro Cicognini David Cinege Craig Citro +Gilles Civario Mike Clarkson Andrew Clegg Brad Clements @@ -180,6 +201,7 @@ Matthew Dixon Cowles Ryan Coyner Christopher A. Craig +Jeremy Craven Laura Creighton Simon Cross Drew Csillag @@ -202,6 +224,7 @@ Arnaud Delobelle Erik Demaine John Dennis +L. Peter Deutsch Roger Dev Philippe Devalkeneer Raghuram Devarakonda @@ -215,6 +238,7 @@ Daniel Dittmar Jaromir Dolecek Ismail Donmez +Robert Donohue Marcos Donolo Dima Dorfman Cesar Douady @@ -263,10 +287,12 @@ Mark Favas Niels Ferguson Sebastian Fernandez +Carl Feynman Vincent Fiack Tomer Filiba Jeffrey Finkelstein Russell Finn +Dan Finnie Nils Fischbeck Frederik Fix Matt Fleming @@ -276,6 +302,7 @@ Amaury Forgeot d'Arc Doug Fort John Fouhy +Stefan Franke Martin Franklin Robin Friedrich Bradley Froehle @@ -293,6 +320,7 @@ Lele Gaifax Santiago Gala Yitzchak Gale +Matthew Gallagher Quentin Gallet-Gilles Raymund Galvin Nitin Ganatra @@ -308,6 +336,7 @@ Gabriel Genellina Christos Georgiou Ben Gertzfield +Nadim Ghaznavi Dinu Gherman Jonathan Giddy Johannes Gijsbers @@ -315,14 +344,18 @@ Christoph Gohlke Tim Golden Chris Gonnerman +Shelley Gooch David Goodger Hans de Graaff +Nathaniel Gray Eddy De Greef +Grant Griffin Duncan Grisby Fabian Groffen John S. Gruber Dag Gruneau Filip Gruszczy?ski +Thomas Guettler Michael Guravage Lars Gust?bel Thomas G?ttler @@ -335,7 +368,9 @@ Bob Halley Jesse Hallio Jun Hamano +Anders Hammarquist Mark Hammond +Harald Hanche-Olsen Manus Hand Milton L. Hankins Stephen Hansen @@ -343,9 +378,13 @@ Lynda Hardman Derek Harland Jason Harper +Travis B. Hartwell Larry Hastings +Tim Hatch Shane Hathaway +Janko Hauser Rycharde Hawkes +Ben Hayden Jochen Hayek Christian Heimes Thomas Heller @@ -371,10 +410,13 @@ Joerg-Cyril Hoehle Gregor Hoffleit Chris Hoffman +Stefan Hoffmeister Albert Hofkamp Tomas Hoger Jonathan Hogg +Steve Holden Akintayo Holder +Thomas Holenstein Gerrit Holl Shane Holloway Rune Holm @@ -389,6 +431,7 @@ Jan Hosang Ken Howard Brad Howes +Mike Hoy Chih-Hao Huang Lawrence Hudson Michael Hudson @@ -407,6 +450,7 @@ Tony Ingraldi John Interrante Bob Ippolito +Roger Irwin Atsuo Ishimoto Paul Jackson Ben Jackson @@ -419,12 +463,15 @@ Thomas Jarosch Drew Jenkins Flemming Kj?r Jensen +Philip H. Jensen Philip Jenvey Chris Jerdonek Jiba +Pedro Diaz Jimenez Orjan Johansen Fredrik Johansson Gregory K. Johnson +Kent Johnson Simon Johnston Nicolas Joly Evan Jones @@ -450,17 +497,20 @@ Ryan Kelly Robert Kern Randall Kern +Jim Kerr Magnus Kessler Lawrence Kesteloot Rafe Kettler Vivek Khera -Akira Kitada Mads Kiilerich +Jan Kim Taek Joo Kim W. Trevor King Paul Kippes Steve Kirsch Sebastian Kirsche +Kamil Kisiel +Akira Kitada Ron Klatchko Bastian Kleineidam Bob Kline @@ -474,7 +524,10 @@ Greg Kochanski Damon Kohler Marko Kohtala +Guido Kollerie +Peter A. Koren Joseph Koshy +Daniel Kozan Jerzy Kozera Maksim Kozyarchuk Stefan Krah @@ -488,10 +541,13 @@ Ivan Krsti? Andrew Kuchling Ralf W. Grosse-Kunstleve +Dave Kuhlman Vladimir Kushnir +Erno Kuusela Kirill Kuzminykh (?????? ?????????) Ross Lagerwall Cameron Laird +Thomas Lamb Torsten Landschoff ?ukasz Langa Tino Lange @@ -508,6 +564,7 @@ Thomas Lee Christopher Lee Luc Lefebvre +Glyph Lefkowitz Vincent Legoll Kip Lehman Joerg Lehmann @@ -515,7 +572,7 @@ Petri Lehtinen Luke Kenneth Casson Leighton Tshepang Lekhonkhobe -Marc-Andre Lemburg +Marc-Andr? Lemburg John Lenton Christopher Tur Lesniewski-Laas Mark Levinson @@ -526,10 +583,13 @@ Shawn Ligocki Martin Ligr Christopher Lindblad +Ulf A. Lindgren Bj?rn Lindqvist Per Lindqvist Eric Lindvall Gregor Lingl +Everett Lipman +Mirko Liss Nick Lockwood Stephanie Lockwood Anne Lord @@ -545,6 +605,8 @@ Jim Lynch Mikael Lyngvig Martin von L?wis +Jeff MacDonald +John Machin Andrew I MacIntyre Tim MacKenzie Nick Maclaren @@ -553,17 +615,22 @@ David Malcolm Ken Manheimer Vladimir Marangozov +Vincent Marchetti David Marek Doug Marien Sven Marnach Alex Martelli Anthony Martin +Westley Mart?nez S?bastien Martini Roger Masse Nick Mathewson +Laura Matson Graham Matthews Dieter Maurer +Daniel May Arnaud Mazin +Rebecca McCreary Kirk McDonald Chris McDonough Greg McFarlane @@ -578,6 +645,7 @@ Bill van Melle Lucas Prado Melo Ezio Melotti +Doug Mennella Brian Merrell Luke Mewburn Carl Meyer @@ -587,6 +655,7 @@ Tom Middleton Stan Mihai Aristotelis Mikropoulos +Paolo Milani Damien Miller Chad Miller Jason V. Miller @@ -600,6 +669,7 @@ The Dragon De Monsyne Skip Montanaro Paul Moore +Ross Moore Derek Morr James A Morrison Alessandro Moura @@ -611,6 +681,7 @@ Neil Muller R. David Murray Piotr Meyer +Dale Nagata John Nagle Takahiro Nakayama Travers Naran @@ -639,11 +710,14 @@ Nigel O'Brian Kevin O'Connor Tim O'Malley +Zooko O'Whielacronx Pascal Oberndoerfer Jeffrey Ollie Adam Olsen Grant Olson +Koray Oner Piet van Oostrum +Tomas Oppelstrup Jason Orendorff Douglas Orr Michele Orr? @@ -652,6 +726,8 @@ Michael Otteneder R. M. Oudkerk Russel Owen +Joonas Paalasmaa +Shriphani Palakodety Ondrej Palkovsky Mike Pall Todd R. Palmer @@ -661,11 +737,13 @@ Peter Parente Alexandre Parenteau Dan Parisien +William Park Harri Pasanen Randy Pausch Samuele Pedroni Marcel van der Peijl Steven Pemberton +Bo Peng Santiago Peres?n Mark Perrego Trevor Perrin @@ -674,6 +752,7 @@ Benjamin Peterson Chris Petrilli Bjorn Pettersen +Justin D. Pettit Geoff Philbrick Gavrie Philipson Adrian Phillips @@ -705,12 +784,12 @@ Brodie Rao Antti Rasinen Sridhar Ratnakumar -Eric Raymond +Eric S. Raymond Edward K. Ream Chris Rebert Marc Recht John Redford -Terry Reedy +Terry J. Reedy Gareth Rees Steve Reeves Lennart Regebro @@ -727,6 +806,7 @@ Nicholas Riley Jean-Claude Rimbault Vlad Riscutia +Wes Rishel Juan M. Bello Rivas Davide Rizzo Anthony Roach @@ -742,6 +822,7 @@ Case Roole Timothy Roscoe Jim Roskind +Guido van Rossum Just van Rossum Hugo van Rossum Saskia van Rossum @@ -757,6 +838,8 @@ Sam Rushing Mark Russell Nick Russo +Chris Ryland +Constantina S. S?bastien Sabl? Suman Saha Hajime Saitou @@ -766,6 +849,8 @@ Ilya Sandler Mark Sapiro Ty Sarna +Hugh Sasse +Bob Savage Ben Sayer sbt Marco Scataglini @@ -778,6 +863,7 @@ Michael Schneider Peter Schneider-Kamp Arvin Schnell +Scott Schram Chad J. Schroeder Sam Schulenburg Stefan Schwarzer @@ -789,6 +875,7 @@ ?iga Seilnach Fred Sells Jiwon Seo +Joakim Sernbrant Roger Serwy Jerry Seutter Denis Severson @@ -796,6 +883,8 @@ Ha Shao Mark Shannon Richard Shapiro +Justin Sheehy +Charlie Shepherd Bruce Sherwood Alexander Shigin Pete Shinners @@ -803,31 +892,40 @@ John W. Shipman Joel Shprentz Itamar Shtull-Trauring +Yue Shuaijie Eric Siegerman Paul Sijben Tim Silk +Michael Simcich +Ionel Simionescu Kirill Simonov Nathan Paul Simons Janne Sinkkonen +Ng Pheng Siong George Sipe J. Sipprell Kragen Sitaker +Michael Sloan Eric V. Smith Christopher Smith Gregory P. Smith +Roy Smith Rafal Smotrzyk Dirk Soede Paul Sokolovsky Cody Somerville Clay Spence Stefan Sperling +Nicholas Spies Per Spilling Joshua Spoerri Noah Spurrier Nathan Srebro RajGopal Srinivasan +Tage Stabell-Kulo Quentin Stafford-Fraser Frank Stajano +Anthony Starks Oliver Steele Greg Stein Chris Stern @@ -844,6 +942,7 @@ Andreas St?hrk Nathan Sullivan Mark Summerfield +Reuben Sumner Hisao Suzuki Andrew Svetlov Kalle Svensson @@ -871,6 +970,7 @@ Oren Tirosh Jason Tishler Christian Tismer +Jim Tittsler Frank J. Tobin R Lindsay Todd Bennett Todd @@ -881,6 +981,7 @@ John Tromp Jason Trowbridge Anthony Tuininga +David Turner Stephen Turner Theodore Turocy Bill Tutt @@ -890,6 +991,7 @@ Roger Upole Michael Urman Hector Urtubia +Ville Vainio Andi Vajda Case Van Horsen Kyle VanderBeek @@ -907,6 +1009,7 @@ Norman Vine Frank Visser Johannes Vogel +Martijn Vries Niki W. Waibel Wojtek Walczak Charles Waldman @@ -921,8 +1024,10 @@ Aaron Watters Henrik Weber Corran Webster +Glyn Webster Stefan Wehr Zack Weinberg +Bob Weiner Edward Welbourne Cliff Wells Rickard Westman @@ -935,6 +1040,7 @@ Gerry Wiener Frank Wierzbicki Bryce "Zooko" Wilcox-O'Hearn +Timothy Wild Jason Williams John Williams Sue Williams @@ -943,6 +1049,7 @@ Frank Willison Greg V. Wilson J Derek Wilson +Paul Winkler Jody Winston Collin Winter Dik Winter @@ -956,6 +1063,8 @@ Klaus-Juergen Wolf Dan Wolfe Richard Wolff +Adam Woodbeck +Steven Work Darren Worrall Gordon Worley Thomas Wouters @@ -966,6 +1075,7 @@ Ka-Ping Yee Bob Yodlowski Danny Yoo +Rory Yorke George Yoshida Masazumi Yoshikawa Arnaud Ysmal @@ -976,5 +1086,6 @@ Mike Zarnstorff Siebren van der Zee Uwe Zessin +Cheng Zhang Tarek Ziad? Peter ?strand -- Repository URL: http://hg.python.org/cpython From chris.jerdonek at gmail.com Fri Sep 14 01:22:09 2012 From: chris.jerdonek at gmail.com (Chris Jerdonek) Date: Thu, 13 Sep 2012 16:22:09 -0700 Subject: [Python-checkins] cpython (2.7): #15437, #15439: merge Doc/ACKS.txt with Misc/ACKS and modify Doc/about.rst In-Reply-To: <3XHwLr547zzQjv@mail.python.org> References: <3XHwLr547zzQjv@mail.python.org> Message-ID: On Thu, Sep 13, 2012 at 4:00 PM, ezio.melotti wrote: > http://hg.python.org/cpython/rev/76dd082d332e > changeset: 79022:76dd082d332e > branch: 2.7 > parent: 79014:8f847f66a49f > user: Ezio Melotti > date: Fri Sep 14 01:58:33 2012 +0300 > summary: > #15437, #15439: merge Doc/ACKS.txt with Misc/ACKS and modify Doc/about.rst accordingly. I also contributed to this. :) --Chris > files: > Doc/ACKS.txt | 231 -------------------------------------- > Doc/about.rst | 9 +- > Misc/ACKS | 119 ++++++++++++++++++- > 3 files changed, 122 insertions(+), 237 deletions(-) > > > diff --git a/Doc/ACKS.txt b/Doc/ACKS.txt > deleted file mode 100644 > --- a/Doc/ACKS.txt > +++ /dev/null > @@ -1,231 +0,0 @@ > -Contributors to the Python Documentation > ----------------------------------------- > - > -This section lists people who have contributed in some way to the Python > -documentation. It is probably not complete -- if you feel that you or > -anyone else should be on this list, please let us know (send email to > -docs at python.org), and we'll be glad to correct the problem. > - > -.. acks:: > - > - * Aahz > - * Michael Abbott > - * Steve Alexander > - * Jim Ahlstrom > - * Fred Allen > - * A. Amoroso > - * Pehr Anderson > - * Oliver Andrich > - * Heidi Annexstad > - * Jes?s Cea Avi?n > - * Manuel Balsera > - * Daniel Barclay > - * Chris Barker > - * Don Bashford > - * Anthony Baxter > - * Alexander Belopolsky > - * Bennett Benson > - * Jonathan Black > - * Robin Boerdijk > - * Michal Bozon > - * Aaron Brancotti > - * Georg Brandl > - * Keith Briggs > - * Ian Bruntlett > - * Lee Busby > - * Arnaud Calmettes > - * Lorenzo M. Catucci > - * Carl Cerecke > - * Mauro Cicognini > - * Gilles Civario > - * Mike Clarkson > - * Steve Clift > - * Dave Cole > - * Matthew Cowles > - * Jeremy Craven > - * Andrew Dalke > - * Ben Darnell > - * L. Peter Deutsch > - * Robert Donohue > - * Fred L. Drake, Jr. > - * Josip Dzolonga > - * Jeff Epler > - * Michael Ernst > - * Blame Andy Eskilsson > - * Carey Evans > - * Martijn Faassen > - * Carl Feynman > - * Dan Finnie > - * Hern?n Mart?nez Foffani > - * Stefan Franke > - * Jim Fulton > - * Peter Funk > - * Lele Gaifax > - * Matthew Gallagher > - * Gabriel Genellina > - * Ben Gertzfield > - * Nadim Ghaznavi > - * Jonathan Giddy > - * Shelley Gooch > - * Nathaniel Gray > - * Grant Griffin > - * Thomas Guettler > - * Anders Hammarquist > - * Mark Hammond > - * Harald Hanche-Olsen > - * Manus Hand > - * Gerhard H?ring > - * Travis B. Hartwell > - * Tim Hatch > - * Janko Hauser > - * Ben Hayden > - * Thomas Heller > - * Bernhard Herzog > - * Magnus L. Hetland > - * Konrad Hinsen > - * Stefan Hoffmeister > - * Albert Hofkamp > - * Gregor Hoffleit > - * Steve Holden > - * Thomas Holenstein > - * Gerrit Holl > - * Rob Hooft > - * Brian Hooper > - * Randall Hopper > - * Mike Hoy > - * Michael Hudson > - * Eric Huss > - * Jeremy Hylton > - * Roger Irwin > - * Jack Jansen > - * Philip H. Jensen > - * Pedro Diaz Jimenez > - * Kent Johnson > - * Lucas de Jonge > - * Andreas Jung > - * Robert Kern > - * Jim Kerr > - * Jan Kim > - * Kamil Kisiel > - * Greg Kochanski > - * Guido Kollerie > - * Peter A. Koren > - * Daniel Kozan > - * Andrew M. Kuchling > - * Dave Kuhlman > - * Erno Kuusela > - * Ross Lagerwall > - * Thomas Lamb > - * Detlef Lannert > - * Piers Lauder > - * Glyph Lefkowitz > - * Robert Lehmann > - * Marc-Andr? Lemburg > - * Ross Light > - * Ulf A. Lindgren > - * Everett Lipman > - * Mirko Liss > - * Martin von L?wis > - * Fredrik Lundh > - * Jeff MacDonald > - * John Machin > - * Andrew MacIntyre > - * Vladimir Marangozov > - * Vincent Marchetti > - * Westley Mart?nez > - * Laura Matson > - * Daniel May > - * Rebecca McCreary > - * Doug Mennella > - * Paolo Milani > - * Skip Montanaro > - * Paul Moore > - * Ross Moore > - * Sjoerd Mullender > - * Dale Nagata > - * Michal Nowikowski > - * Steffen Daode Nurpmeso > - * Ng Pheng Siong > - * Koray Oner > - * Tomas Oppelstrup > - * Denis S. Otkidach > - * Zooko O'Whielacronx > - * Shriphani Palakodety > - * William Park > - * Joonas Paalasmaa > - * Harri Pasanen > - * Bo Peng > - * Tim Peters > - * Benjamin Peterson > - * Christopher Petrilli > - * Justin D. Pettit > - * Chris Phoenix > - * Fran?ois Pinard > - * Paul Prescod > - * Eric S. Raymond > - * Edward K. Ream > - * Terry J. Reedy > - * Sean Reifschneider > - * Bernhard Reiter > - * Armin Rigo > - * Wes Rishel > - * Armin Ronacher > - * Jim Roskind > - * Guido van Rossum > - * Donald Wallace Rouse II > - * Mark Russell > - * Nick Russo > - * Chris Ryland > - * Constantina S. > - * Hugh Sasse > - * Bob Savage > - * Scott Schram > - * Neil Schemenauer > - * Barry Scott > - * Joakim Sernbrant > - * Justin Sheehy > - * Charlie Shepherd > - * Yue Shuaijie > - * Michael Simcich > - * Ionel Simionescu > - * Michael Sloan > - * Gregory P. Smith > - * Roy Smith > - * Clay Spence > - * Nicholas Spies > - * Tage Stabell-Kulo > - * Frank Stajano > - * Anthony Starks > - * Greg Stein > - * Peter Stoehr > - * Mark Summerfield > - * Reuben Sumner > - * Kalle Svensson > - * Jim Tittsler > - * David Turner > - * Sandro Tosi > - * Ville Vainio > - * Martijn Vries > - * Charles G. Waldman > - * Greg Ward > - * Barry Warsaw > - * Corran Webster > - * Glyn Webster > - * Bob Weiner > - * Eddy Welbourne > - * Jeff Wheeler > - * Mats Wichmann > - * Gerry Wiener > - * Timothy Wild > - * Paul Winkler > - * Collin Winter > - * Blake Winton > - * Dan Wolfe > - * Adam Woodbeck > - * Steven Work > - * Thomas Wouters > - * Ka-Ping Yee > - * Rory Yorke > - * Moshe Zadka > - * Milan Zamazal > - * Cheng Zhang > diff --git a/Doc/about.rst b/Doc/about.rst > --- a/Doc/about.rst > +++ b/Doc/about.rst > @@ -29,8 +29,13 @@ > See :ref:`reporting-bugs` for information how to report bugs in this > documentation, or Python itself. > > -.. including the ACKS file here so that it can be maintained separately > -.. include:: ACKS.txt > + > +Contributors to the Python Documentation > +---------------------------------------- > + > +Many people have contributed to the Python language, the Python standard > +library, and the Python documentation. See :source:`Misc/ACKS` in the Python > +source distribution for a partial list of contributors. > > It is only with the input and contributions of the Python community > that Python has such wonderful documentation -- Thank You! > diff --git a/Misc/ACKS b/Misc/ACKS > --- a/Misc/ACKS > +++ b/Misc/ACKS > @@ -11,25 +11,33 @@ > PS: In the standard Python distribution, this file is encoded in UTF-8 > and the list is in rough alphabetical order by last names. > > +Aahz > +Michael Abbott > David Abrahams > Jim Ahlstrom > Farhan Ahmad > Nir Aides > Yaniv Aknin > Jyrki Alakuijala > +Steve Alexander > +Fred Allen > Billy G. Allie > Kevin Altis > Joe Amenta > +A. Amoroso > Mark Anacker > Anders Andersen > John Anderson > +Pehr Anderson > Erik Anders?n > Oliver Andrich > Ross Andrus > +Heidi Annexstad > ?ric Araujo > Jason Asbahr > David Ascher > Chris AtLee > +Jes?s Cea Avi?n > John Aycock > Jan-Hein B?hrman > Donovan Baarda > @@ -41,8 +49,10 @@ > Greg Ball > Luigi Ballabio > Jeff Balogh > +Manuel Balsera > Matt Bandy > Michael J. Barber > +Daniel Barclay > Chris Barker > Anton Barkovsky > Nick Barnes > @@ -51,6 +61,7 @@ > Cesar Eduardo Barros > Des Barry > Ulf Bartelt > +Don Bashford > Nick Bastin > Jeff Bauer > Mike Bayer > @@ -69,6 +80,7 @@ > Alexander ?????? Belopolsky > Andrew Bennetts > Andy Bensky > +Bennett Benson > Michel Van den Bergh > Eric Beser > Steven Bethard > @@ -80,6 +92,7 @@ > Philippe Biondi > Stuart Bishop > Roy Bixler > +Jonathan Black > Mike Bland > Martin Bless > Pablo Bleyer > @@ -88,6 +101,7 @@ > Finn Bock > Paul Boddie > Matthew Boedicker > +Robin Boerdijk > David Bolen > Gawain Bolton > Gregory Bond > @@ -96,13 +110,16 @@ > Eric Bouck > Thierry Bousch > Sebastian Boving > +Michal Bozon > Jeff Bradberry > +Aaron Brancotti > Monty Brandenberg > Georg Brandl > Christopher Brannon > Terrence Brannon > Dave Brennan > Tom Bridgman > +Keith Briggs > Richard Brodie > Michael Broghton > Daniel Brotsky > @@ -111,6 +128,7 @@ > Oleg Broytmann > Dave Brueck > Francisco Mart?n Brugu? > +Ian Bruntlett > Stan Bubrouski > Erik de Bueger > Dick Bulterman > @@ -134,6 +152,7 @@ > Donn Cave > Charles Cazabon > Per Cederqvist > +Carl Cerecke > Octavian Cerna > Pascal Chambon > John Chandler > @@ -151,8 +170,10 @@ > Anders Chrigstr?m > Tom Christiansen > Vadim Chugunov > +Mauro Cicognini > David Cinege > Craig Citro > +Gilles Civario > Mike Clarkson > Andrew Clegg > Brad Clements > @@ -180,6 +201,7 @@ > Matthew Dixon Cowles > Ryan Coyner > Christopher A. Craig > +Jeremy Craven > Laura Creighton > Simon Cross > Drew Csillag > @@ -202,6 +224,7 @@ > Arnaud Delobelle > Erik Demaine > John Dennis > +L. Peter Deutsch > Roger Dev > Philippe Devalkeneer > Raghuram Devarakonda > @@ -215,6 +238,7 @@ > Daniel Dittmar > Jaromir Dolecek > Ismail Donmez > +Robert Donohue > Marcos Donolo > Dima Dorfman > Cesar Douady > @@ -263,10 +287,12 @@ > Mark Favas > Niels Ferguson > Sebastian Fernandez > +Carl Feynman > Vincent Fiack > Tomer Filiba > Jeffrey Finkelstein > Russell Finn > +Dan Finnie > Nils Fischbeck > Frederik Fix > Matt Fleming > @@ -276,6 +302,7 @@ > Amaury Forgeot d'Arc > Doug Fort > John Fouhy > +Stefan Franke > Martin Franklin > Robin Friedrich > Bradley Froehle > @@ -293,6 +320,7 @@ > Lele Gaifax > Santiago Gala > Yitzchak Gale > +Matthew Gallagher > Quentin Gallet-Gilles > Raymund Galvin > Nitin Ganatra > @@ -308,6 +336,7 @@ > Gabriel Genellina > Christos Georgiou > Ben Gertzfield > +Nadim Ghaznavi > Dinu Gherman > Jonathan Giddy > Johannes Gijsbers > @@ -315,14 +344,18 @@ > Christoph Gohlke > Tim Golden > Chris Gonnerman > +Shelley Gooch > David Goodger > Hans de Graaff > +Nathaniel Gray > Eddy De Greef > +Grant Griffin > Duncan Grisby > Fabian Groffen > John S. Gruber > Dag Gruneau > Filip Gruszczy?ski > +Thomas Guettler > Michael Guravage > Lars Gust?bel > Thomas G?ttler > @@ -335,7 +368,9 @@ > Bob Halley > Jesse Hallio > Jun Hamano > +Anders Hammarquist > Mark Hammond > +Harald Hanche-Olsen > Manus Hand > Milton L. Hankins > Stephen Hansen > @@ -343,9 +378,13 @@ > Lynda Hardman > Derek Harland > Jason Harper > +Travis B. Hartwell > Larry Hastings > +Tim Hatch > Shane Hathaway > +Janko Hauser > Rycharde Hawkes > +Ben Hayden > Jochen Hayek > Christian Heimes > Thomas Heller > @@ -371,10 +410,13 @@ > Joerg-Cyril Hoehle > Gregor Hoffleit > Chris Hoffman > +Stefan Hoffmeister > Albert Hofkamp > Tomas Hoger > Jonathan Hogg > +Steve Holden > Akintayo Holder > +Thomas Holenstein > Gerrit Holl > Shane Holloway > Rune Holm > @@ -389,6 +431,7 @@ > Jan Hosang > Ken Howard > Brad Howes > +Mike Hoy > Chih-Hao Huang > Lawrence Hudson > Michael Hudson > @@ -407,6 +450,7 @@ > Tony Ingraldi > John Interrante > Bob Ippolito > +Roger Irwin > Atsuo Ishimoto > Paul Jackson > Ben Jackson > @@ -419,12 +463,15 @@ > Thomas Jarosch > Drew Jenkins > Flemming Kj?r Jensen > +Philip H. Jensen > Philip Jenvey > Chris Jerdonek > Jiba > +Pedro Diaz Jimenez > Orjan Johansen > Fredrik Johansson > Gregory K. Johnson > +Kent Johnson > Simon Johnston > Nicolas Joly > Evan Jones > @@ -450,17 +497,20 @@ > Ryan Kelly > Robert Kern > Randall Kern > +Jim Kerr > Magnus Kessler > Lawrence Kesteloot > Rafe Kettler > Vivek Khera > -Akira Kitada > Mads Kiilerich > +Jan Kim > Taek Joo Kim > W. Trevor King > Paul Kippes > Steve Kirsch > Sebastian Kirsche > +Kamil Kisiel > +Akira Kitada > Ron Klatchko > Bastian Kleineidam > Bob Kline > @@ -474,7 +524,10 @@ > Greg Kochanski > Damon Kohler > Marko Kohtala > +Guido Kollerie > +Peter A. Koren > Joseph Koshy > +Daniel Kozan > Jerzy Kozera > Maksim Kozyarchuk > Stefan Krah > @@ -488,10 +541,13 @@ > Ivan Krsti? > Andrew Kuchling > Ralf W. Grosse-Kunstleve > +Dave Kuhlman > Vladimir Kushnir > +Erno Kuusela > Kirill Kuzminykh (?????? ?????????) > Ross Lagerwall > Cameron Laird > +Thomas Lamb > Torsten Landschoff > ?ukasz Langa > Tino Lange > @@ -508,6 +564,7 @@ > Thomas Lee > Christopher Lee > Luc Lefebvre > +Glyph Lefkowitz > Vincent Legoll > Kip Lehman > Joerg Lehmann > @@ -515,7 +572,7 @@ > Petri Lehtinen > Luke Kenneth Casson Leighton > Tshepang Lekhonkhobe > -Marc-Andre Lemburg > +Marc-Andr? Lemburg > John Lenton > Christopher Tur Lesniewski-Laas > Mark Levinson > @@ -526,10 +583,13 @@ > Shawn Ligocki > Martin Ligr > Christopher Lindblad > +Ulf A. Lindgren > Bj?rn Lindqvist > Per Lindqvist > Eric Lindvall > Gregor Lingl > +Everett Lipman > +Mirko Liss > Nick Lockwood > Stephanie Lockwood > Anne Lord > @@ -545,6 +605,8 @@ > Jim Lynch > Mikael Lyngvig > Martin von L?wis > +Jeff MacDonald > +John Machin > Andrew I MacIntyre > Tim MacKenzie > Nick Maclaren > @@ -553,17 +615,22 @@ > David Malcolm > Ken Manheimer > Vladimir Marangozov > +Vincent Marchetti > David Marek > Doug Marien > Sven Marnach > Alex Martelli > Anthony Martin > +Westley Mart?nez > S?bastien Martini > Roger Masse > Nick Mathewson > +Laura Matson > Graham Matthews > Dieter Maurer > +Daniel May > Arnaud Mazin > +Rebecca McCreary > Kirk McDonald > Chris McDonough > Greg McFarlane > @@ -578,6 +645,7 @@ > Bill van Melle > Lucas Prado Melo > Ezio Melotti > +Doug Mennella > Brian Merrell > Luke Mewburn > Carl Meyer > @@ -587,6 +655,7 @@ > Tom Middleton > Stan Mihai > Aristotelis Mikropoulos > +Paolo Milani > Damien Miller > Chad Miller > Jason V. Miller > @@ -600,6 +669,7 @@ > The Dragon De Monsyne > Skip Montanaro > Paul Moore > +Ross Moore > Derek Morr > James A Morrison > Alessandro Moura > @@ -611,6 +681,7 @@ > Neil Muller > R. David Murray > Piotr Meyer > +Dale Nagata > John Nagle > Takahiro Nakayama > Travers Naran > @@ -639,11 +710,14 @@ > Nigel O'Brian > Kevin O'Connor > Tim O'Malley > +Zooko O'Whielacronx > Pascal Oberndoerfer > Jeffrey Ollie > Adam Olsen > Grant Olson > +Koray Oner > Piet van Oostrum > +Tomas Oppelstrup > Jason Orendorff > Douglas Orr > Michele Orr? > @@ -652,6 +726,8 @@ > Michael Otteneder > R. M. Oudkerk > Russel Owen > +Joonas Paalasmaa > +Shriphani Palakodety > Ondrej Palkovsky > Mike Pall > Todd R. Palmer > @@ -661,11 +737,13 @@ > Peter Parente > Alexandre Parenteau > Dan Parisien > +William Park > Harri Pasanen > Randy Pausch > Samuele Pedroni > Marcel van der Peijl > Steven Pemberton > +Bo Peng > Santiago Peres?n > Mark Perrego > Trevor Perrin > @@ -674,6 +752,7 @@ > Benjamin Peterson > Chris Petrilli > Bjorn Pettersen > +Justin D. Pettit > Geoff Philbrick > Gavrie Philipson > Adrian Phillips > @@ -705,12 +784,12 @@ > Brodie Rao > Antti Rasinen > Sridhar Ratnakumar > -Eric Raymond > +Eric S. Raymond > Edward K. Ream > Chris Rebert > Marc Recht > John Redford > -Terry Reedy > +Terry J. Reedy > Gareth Rees > Steve Reeves > Lennart Regebro > @@ -727,6 +806,7 @@ > Nicholas Riley > Jean-Claude Rimbault > Vlad Riscutia > +Wes Rishel > Juan M. Bello Rivas > Davide Rizzo > Anthony Roach > @@ -742,6 +822,7 @@ > Case Roole > Timothy Roscoe > Jim Roskind > +Guido van Rossum > Just van Rossum > Hugo van Rossum > Saskia van Rossum > @@ -757,6 +838,8 @@ > Sam Rushing > Mark Russell > Nick Russo > +Chris Ryland > +Constantina S. > S?bastien Sabl? > Suman Saha > Hajime Saitou > @@ -766,6 +849,8 @@ > Ilya Sandler > Mark Sapiro > Ty Sarna > +Hugh Sasse > +Bob Savage > Ben Sayer > sbt > Marco Scataglini > @@ -778,6 +863,7 @@ > Michael Schneider > Peter Schneider-Kamp > Arvin Schnell > +Scott Schram > Chad J. Schroeder > Sam Schulenburg > Stefan Schwarzer > @@ -789,6 +875,7 @@ > ?iga Seilnach > Fred Sells > Jiwon Seo > +Joakim Sernbrant > Roger Serwy > Jerry Seutter > Denis Severson > @@ -796,6 +883,8 @@ > Ha Shao > Mark Shannon > Richard Shapiro > +Justin Sheehy > +Charlie Shepherd > Bruce Sherwood > Alexander Shigin > Pete Shinners > @@ -803,31 +892,40 @@ > John W. Shipman > Joel Shprentz > Itamar Shtull-Trauring > +Yue Shuaijie > Eric Siegerman > Paul Sijben > Tim Silk > +Michael Simcich > +Ionel Simionescu > Kirill Simonov > Nathan Paul Simons > Janne Sinkkonen > +Ng Pheng Siong > George Sipe > J. Sipprell > Kragen Sitaker > +Michael Sloan > Eric V. Smith > Christopher Smith > Gregory P. Smith > +Roy Smith > Rafal Smotrzyk > Dirk Soede > Paul Sokolovsky > Cody Somerville > Clay Spence > Stefan Sperling > +Nicholas Spies > Per Spilling > Joshua Spoerri > Noah Spurrier > Nathan Srebro > RajGopal Srinivasan > +Tage Stabell-Kulo > Quentin Stafford-Fraser > Frank Stajano > +Anthony Starks > Oliver Steele > Greg Stein > Chris Stern > @@ -844,6 +942,7 @@ > Andreas St?hrk > Nathan Sullivan > Mark Summerfield > +Reuben Sumner > Hisao Suzuki > Andrew Svetlov > Kalle Svensson > @@ -871,6 +970,7 @@ > Oren Tirosh > Jason Tishler > Christian Tismer > +Jim Tittsler > Frank J. Tobin > R Lindsay Todd > Bennett Todd > @@ -881,6 +981,7 @@ > John Tromp > Jason Trowbridge > Anthony Tuininga > +David Turner > Stephen Turner > Theodore Turocy > Bill Tutt > @@ -890,6 +991,7 @@ > Roger Upole > Michael Urman > Hector Urtubia > +Ville Vainio > Andi Vajda > Case Van Horsen > Kyle VanderBeek > @@ -907,6 +1009,7 @@ > Norman Vine > Frank Visser > Johannes Vogel > +Martijn Vries > Niki W. Waibel > Wojtek Walczak > Charles Waldman > @@ -921,8 +1024,10 @@ > Aaron Watters > Henrik Weber > Corran Webster > +Glyn Webster > Stefan Wehr > Zack Weinberg > +Bob Weiner > Edward Welbourne > Cliff Wells > Rickard Westman > @@ -935,6 +1040,7 @@ > Gerry Wiener > Frank Wierzbicki > Bryce "Zooko" Wilcox-O'Hearn > +Timothy Wild > Jason Williams > John Williams > Sue Williams > @@ -943,6 +1049,7 @@ > Frank Willison > Greg V. Wilson > J Derek Wilson > +Paul Winkler > Jody Winston > Collin Winter > Dik Winter > @@ -956,6 +1063,8 @@ > Klaus-Juergen Wolf > Dan Wolfe > Richard Wolff > +Adam Woodbeck > +Steven Work > Darren Worrall > Gordon Worley > Thomas Wouters > @@ -966,6 +1075,7 @@ > Ka-Ping Yee > Bob Yodlowski > Danny Yoo > +Rory Yorke > George Yoshida > Masazumi Yoshikawa > Arnaud Ysmal > @@ -976,5 +1086,6 @@ > Mike Zarnstorff > Siebren van der Zee > Uwe Zessin > +Cheng Zhang > Tarek Ziad? > Peter ?strand > > -- > Repository URL: http://hg.python.org/cpython > > _______________________________________________ > Python-checkins mailing list > Python-checkins at python.org > http://mail.python.org/mailman/listinfo/python-checkins > From ezio.melotti at gmail.com Fri Sep 14 01:50:47 2012 From: ezio.melotti at gmail.com (Ezio Melotti) Date: Fri, 14 Sep 2012 02:50:47 +0300 Subject: [Python-checkins] [Python-Dev] cpython (2.7): #15437, #15439: merge Doc/ACKS.txt with Misc/ACKS and modify Doc/about.rst In-Reply-To: References: <3XHwLr547zzQjv@mail.python.org> Message-ID: On Fri, Sep 14, 2012 at 2:22 AM, Chris Jerdonek wrote: > On Thu, Sep 13, 2012 at 4:00 PM, ezio.melotti > wrote: >> http://hg.python.org/cpython/rev/76dd082d332e >> changeset: 79022:76dd082d332e >> branch: 2.7 >> parent: 79014:8f847f66a49f >> user: Ezio Melotti >> date: Fri Sep 14 01:58:33 2012 +0300 >> summary: >> #15437, #15439: merge Doc/ACKS.txt with Misc/ACKS and modify Doc/about.rst accordingly. > > I also contributed to this. :) > Yes, with all these ACKS and names I forgot to mention yours in the commit message :) Thanks again for writing the script that automatically merged all the names! Best Regards, Ezio Melotti > --Chris > From python-checkins at python.org Fri Sep 14 06:00:33 2012 From: python-checkins at python.org (ezio.melotti) Date: Fri, 14 Sep 2012 06:00:33 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE1ODMxOiBkb2N1?= =?utf-8?q?ment_multiple_signatures_on_different_lines=2E__Patch_by_Chris?= Message-ID: <3XJ30x71f7zQhN@mail.python.org> http://hg.python.org/cpython/rev/b01eb870f84f changeset: 79023:b01eb870f84f branch: 3.2 parent: 79020:48185b0f7b8a user: Ezio Melotti date: Fri Sep 14 06:32:35 2012 +0300 summary: #15831: document multiple signatures on different lines. Patch by Chris Jerdonek. files: Doc/library/argparse.rst | 9 ++- Doc/library/configparser.rst | 3 +- Doc/library/curses.rst | 44 ++++++++++++++------ Doc/library/functions.rst | 38 +++++++++++------ Doc/library/http.client.rst | 8 ++- Doc/library/itertools.rst | 3 +- Doc/library/multiprocessing.rst | 2 +- Doc/library/optparse.rst | 6 +- Doc/library/ossaudiodev.rst | 3 +- Doc/library/random.rst | 11 ++-- Doc/library/socket.rst | 3 +- Doc/library/syslog.rst | 3 +- Doc/library/tkinter.tix.rst | 2 +- 13 files changed, 89 insertions(+), 46 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -130,9 +130,12 @@ ArgumentParser objects ---------------------- -.. class:: ArgumentParser([description], [epilog], [prog], [usage], [add_help], \ - [argument_default], [parents], [prefix_chars], \ - [conflict_handler], [formatter_class]) +.. class:: ArgumentParser(prog=None, usage=None, description=None, \ + epilog=None, parents=[], \ + formatter_class=argparse.HelpFormatter, \ + prefix_chars='-', fromfile_prefix_chars=None, \ + argument_default=None, conflict_handler='error', \ + add_help=True) Create a new :class:`ArgumentParser` object. Each parameter has its own more detailed description below, but in short they are: diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -1051,7 +1051,8 @@ *fallback*. - .. method:: items([section], raw=False, vars=None) + .. method:: items(raw=False, vars=None) + items(section, raw=False, vars=None) When *section* is not given, return a list of *section_name*, *section_proxy* pairs, including DEFAULTSECT. diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -377,7 +377,8 @@ is to be displayed. -.. function:: newwin([nlines, ncols,] begin_y, begin_x) +.. function:: newwin(begin_y, begin_x) + newwin(nlines, ncols, begin_y, begin_x) Return a new window, whose left-upper corner is at ``(begin_y, begin_x)``, and whose height/width is *nlines*/*ncols*. @@ -645,7 +646,8 @@ the following methods: -.. method:: window.addch([y, x,] ch[, attr]) +.. method:: window.addch(ch[, attr]) + window.addch(y, x, ch[, attr]) .. note:: @@ -659,13 +661,15 @@ position and attributes are the current settings for the window object. -.. method:: window.addnstr([y, x,] str, n[, attr]) +.. method:: window.addnstr(str, n[, attr]) + window.addnstr(y, x, str, n[, attr]) Paint at most *n* characters of the string *str* at ``(y, x)`` with attributes *attr*, overwriting anything previously on the display. -.. method:: window.addstr([y, x,] str[, attr]) +.. method:: window.addstr(str[, attr]) + window.addstr(y, x, str[, attr]) Paint the string *str* at ``(y, x)`` with attributes *attr*, overwriting anything previously on the display. @@ -752,7 +756,10 @@ *bs* are *horch*. The default corner characters are always used by this function. -.. method:: window.chgat([y, x, ] [num,] attr) +.. method:: window.chgat(attr) + window.chgat(num, attr) + window.chgat(y, x, attr) + window.chgat(y, x, num, attr) Set the attributes of *num* characters at the current cursor position, or at position ``(y, x)`` if supplied. If no value of *num* is given or *num* = -1, @@ -801,7 +808,8 @@ Delete the line under the cursor. All following lines are moved up by one line. -.. method:: window.derwin([nlines, ncols,] begin_y, begin_x) +.. method:: window.derwin(begin_y, begin_x) + window.derwin(nlines, ncols, begin_y, begin_x) An abbreviation for "derive window", :meth:`derwin` is the same as calling :meth:`subwin`, except that *begin_y* and *begin_x* are relative to the origin @@ -876,7 +884,8 @@ upper-left corner. -.. method:: window.hline([y, x,] ch, n) +.. method:: window.hline(ch, n) + window.hline(y, x, ch, n) Display a horizontal line starting at ``(y, x)`` with length *n* consisting of the character *ch*. @@ -910,7 +919,8 @@ the character proper, and upper bits are the attributes. -.. method:: window.insch([y, x,] ch[, attr]) +.. method:: window.insch(ch[, attr]) + window.insch(y, x, ch[, attr]) Paint character *ch* at ``(y, x)`` with attributes *attr*, moving the line from position *x* right by one character. @@ -931,7 +941,8 @@ line. -.. method:: window.insnstr([y, x,] str, n [, attr]) +.. method:: window.insnstr(str, n[, attr]) + window.insnstr(y, x, str, n[, attr]) Insert a character string (as many characters as will fit on the line) before the character under the cursor, up to *n* characters. If *n* is zero or @@ -940,7 +951,8 @@ The cursor position does not change (after moving to *y*, *x*, if specified). -.. method:: window.insstr([y, x, ] str [, attr]) +.. method:: window.insstr(str[, attr]) + window.insstr(y, x, str[, attr]) Insert a character string (as many characters as will fit on the line) before the character under the cursor. All characters to the right of the cursor are @@ -948,7 +960,8 @@ position does not change (after moving to *y*, *x*, if specified). -.. method:: window.instr([y, x] [, n]) +.. method:: window.instr([n]) + window.instr(y, x[, n]) Return a string of characters, extracted from the window starting at the current cursor position, or at *y*, *x* if specified. Attributes are stripped @@ -1123,13 +1136,15 @@ Turn on attribute *A_STANDOUT*. -.. method:: window.subpad([nlines, ncols,] begin_y, begin_x) +.. method:: window.subpad(begin_y, begin_x) + window.subpad(nlines, ncols, begin_y, begin_x) Return a sub-window, whose upper-left corner is at ``(begin_y, begin_x)``, and whose width/height is *ncols*/*nlines*. -.. method:: window.subwin([nlines, ncols,] begin_y, begin_x) +.. method:: window.subwin(begin_y, begin_x) + window.subwin(nlines, ncols, begin_y, begin_x) Return a sub-window, whose upper-left corner is at ``(begin_y, begin_x)``, and whose width/height is *ncols*/*nlines*. @@ -1186,7 +1201,8 @@ :meth:`refresh`. -.. method:: window.vline([y, x,] ch, n) +.. method:: window.vline(ch, n) + window.vline(y, x, ch, n) Display a vertical line starting at ``(y, x)`` with length *n* consisting of the character *ch*. diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -727,11 +727,16 @@ already arranged into argument tuples, see :func:`itertools.starmap`\. -.. function:: max(iterable[, args...], *[, key]) +.. function:: max(iterable, *[, key]) + max(arg1, arg2, *args[, key]) - With a single argument *iterable*, return the largest item of a non-empty - iterable (such as a string, tuple or list). With more than one argument, return - the largest of the arguments. + Return the largest item in an iterable or the largest of two or more + arguments. + + If one positional argument is provided, *iterable* must be a non-empty + iterable (such as a non-empty string, tuple or list). The largest item + in the iterable is returned. If two or more positional arguments are + provided, the largest of the positional arguments is returned. The optional keyword-only *key* argument specifies a one-argument ordering function like that used for :meth:`list.sort`. @@ -750,11 +755,16 @@ :ref:`typememoryview` for more information. -.. function:: min(iterable[, args...], *[, key]) +.. function:: min(iterable, *[, key]) + min(arg1, arg2, *args[, key]) - With a single argument *iterable*, return the smallest item of a non-empty - iterable (such as a string, tuple or list). With more than one argument, return - the smallest of the arguments. + Return the smallest item in an iterable or the smallest of two or more + arguments. + + If one positional argument is provided, *iterable* must be a non-empty + iterable (such as a non-empty string, tuple or list). The smallest item + in the iterable is returned. If two or more positional arguments are + provided, the smallest of the positional arguments is returned. The optional keyword-only *key* argument specifies a one-argument ordering function like that used for :meth:`list.sort`. @@ -957,16 +967,16 @@ must be of integer types, and *y* must be non-negative. -.. function:: print([object, ...], *, sep=' ', end='\\n', file=sys.stdout) +.. function:: print(*objects, sep=' ', end='\\n', file=sys.stdout) - Print *object*\(s) to the stream *file*, separated by *sep* and followed by + Print *objects* to the stream *file*, separated by *sep* and followed by *end*. *sep*, *end* and *file*, if present, must be given as keyword arguments. All non-keyword arguments are converted to strings like :func:`str` does and written to the stream, separated by *sep* and followed by *end*. Both *sep* and *end* must be strings; they can also be ``None``, which means to use the - default values. If no *object* is given, :func:`print` will just write + default values. If no *objects* are given, :func:`print` will just write *end*. The *file* argument must be an object with a ``write(string)`` method; if it @@ -1045,7 +1055,8 @@ .. XXX does accept objects with __index__ too -.. function:: range([start,] stop[, step]) +.. function:: range(stop) + range(start, stop[, step]) This is a versatile function to create iterables yielding arithmetic progressions. It is most often used in :keyword:`for` loops. The arguments @@ -1160,7 +1171,8 @@ ``x.foobar = 123``. -.. function:: slice([start,] stop[, step]) +.. function:: slice(stop) + slice(start, stop[, step]) .. index:: single: Numerical Python diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -27,7 +27,8 @@ The module provides the following classes: -.. class:: HTTPConnection(host, port=None[, strict[, timeout[, source_address]]]) +.. class:: HTTPConnection(host, port=None[, strict][, timeout], \ + source_address=None) An :class:`HTTPConnection` instance represents one transaction with an HTTP server. It should be instantiated passing it a host and optional port @@ -55,7 +56,10 @@ are not supported anymore. -.. class:: HTTPSConnection(host, port=None, key_file=None, cert_file=None[, strict[, timeout[, source_address]]], *, context=None, check_hostname=None) +.. class:: HTTPSConnection(host, port=None, key_file=None, \ + cert_file=None[, strict][, timeout], \ + source_address=None, *, context=None, \ + check_hostname=None) A subclass of :class:`HTTPConnection` that uses SSL for communication with secure servers. Default port is ``443``. If *context* is specified, it diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -363,7 +363,8 @@ self.currkey = self.keyfunc(self.currvalue) -.. function:: islice(iterable, [start,] stop [, step]) +.. function:: islice(iterable, stop) + islice(iterable, start, stop[, step]) Make an iterator that returns selected elements from the iterable. If *start* is non-zero, then elements from the iterable are skipped until start is reached. diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -298,7 +298,7 @@ :class:`Process` and exceptions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. class:: Process([group[, target[, name[, args[, kwargs]]]]]) +.. class:: Process(group=None, target=None, name=None, args=(), kwargs={}) Process objects represent activity that is run in a separate process. The :class:`Process` class has equivalents of all the methods of diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -273,7 +273,8 @@ strings as you like (including zero), as long as there is at least one option string overall. -The option strings passed to :meth:`add_option` are effectively labels for the +The option strings passed to :meth:`OptionParser.add_option` are effectively +labels for the option defined by that call. For brevity, we will frequently refer to *encountering an option* on the command line; in reality, :mod:`optparse` encounters *option strings* and looks up options from them. @@ -892,7 +893,8 @@ The canonical way to create an :class:`Option` instance is with the :meth:`add_option` method of :class:`OptionParser`. -.. method:: OptionParser.add_option(opt_str[, ...], attr=value, ...) +.. method:: OptionParser.add_option(option) + OptionParser.add_option(*opt_str, attr=value, ...) To define an option with only a short option string:: diff --git a/Doc/library/ossaudiodev.rst b/Doc/library/ossaudiodev.rst --- a/Doc/library/ossaudiodev.rst +++ b/Doc/library/ossaudiodev.rst @@ -63,7 +63,8 @@ ``ossaudiodev.error``.) -.. function:: open([device, ]mode) +.. function:: open(mode) + open(device, mode) Open an audio device and return an OSS audio device object. This object supports many file-like methods, such as :meth:`read`, :meth:`write`, and diff --git a/Doc/library/random.rst b/Doc/library/random.rst --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -46,20 +46,20 @@ Bookkeeping functions: -.. function:: seed([x], version=2) +.. function:: seed(a=None, version=2) Initialize the random number generator. - If *x* is omitted or ``None``, the current system time is used. If + If *a* is omitted or ``None``, the current system time is used. If randomness sources are provided by the operating system, they are used instead of the system time (see the :func:`os.urandom` function for details on availability). - If *x* is an int, it is used directly. + If *a* is an int, it is used directly. With version 2 (the default), a :class:`str`, :class:`bytes`, or :class:`bytearray` object gets converted to an :class:`int` and all of its bits are used. With version 1, - the :func:`hash` of *x* is used instead. + the :func:`hash` of *a* is used instead. .. versionchanged:: 3.2 Moved to the version 2 scheme which uses all of the bits in a string seed. @@ -87,7 +87,8 @@ Functions for integers: -.. function:: randrange([start,] stop[, step]) +.. function:: randrange(stop) + randrange(start, stop[, step]) Return a randomly selected element from ``range(start, stop, step)``. This is equivalent to ``choice(range(start, stop, step))``, but doesn't actually build a diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -745,7 +745,8 @@ much data, if any, was successfully sent. -.. method:: socket.sendto(bytes[, flags], address) +.. method:: socket.sendto(bytes, address) + socket.sendto(bytes, flags, address) Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by *address*. The optional *flags* diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -17,7 +17,8 @@ The module defines the following functions: -.. function:: syslog([priority,] message) +.. function:: syslog(message) + syslog(priority, message) Send the string *message* to the system logger. A trailing newline is added if necessary. Each message is tagged with a priority composed of a diff --git a/Doc/library/tkinter.tix.rst b/Doc/library/tkinter.tix.rst --- a/Doc/library/tkinter.tix.rst +++ b/Doc/library/tkinter.tix.rst @@ -504,7 +504,7 @@ print(root.tix_configure()) -.. method:: tixCommand.tix_configure([cnf,] **kw) +.. method:: tixCommand.tix_configure(cnf=None, **kw) Query or modify the configuration options of the Tix application context. If no option is specified, returns a dictionary all of the available options. If -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 14 06:01:06 2012 From: python-checkins at python.org (ezio.melotti) Date: Fri, 14 Sep 2012 06:01:06 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_=2315831=3A_merge_with_3=2E2?= Message-ID: <3XJ31Z0kkBzQm8@mail.python.org> http://hg.python.org/cpython/rev/0ed61ee823d8 changeset: 79024:0ed61ee823d8 parent: 79021:2b4a89f82485 parent: 79023:b01eb870f84f user: Ezio Melotti date: Fri Sep 14 06:35:09 2012 +0300 summary: #15831: merge with 3.2 files: Doc/library/argparse.rst | 9 ++- Doc/library/configparser.rst | 3 +- Doc/library/curses.rst | 44 ++++++++++++++------ Doc/library/functions.rst | 38 +++++++++++------ Doc/library/http.client.rst | 8 ++- Doc/library/inspect.rst | 4 +- Doc/library/itertools.rst | 3 +- Doc/library/multiprocessing.rst | 3 +- Doc/library/optparse.rst | 6 +- Doc/library/ossaudiodev.rst | 3 +- Doc/library/random.rst | 11 ++-- Doc/library/socket.rst | 3 +- Doc/library/stdtypes.rst | 3 +- Doc/library/syslog.rst | 3 +- Doc/library/tkinter.tix.rst | 2 +- 15 files changed, 94 insertions(+), 49 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -130,9 +130,12 @@ ArgumentParser objects ---------------------- -.. class:: ArgumentParser([description], [epilog], [prog], [usage], [add_help], \ - [argument_default], [parents], [prefix_chars], \ - [conflict_handler], [formatter_class]) +.. class:: ArgumentParser(prog=None, usage=None, description=None, \ + epilog=None, parents=[], \ + formatter_class=argparse.HelpFormatter, \ + prefix_chars='-', fromfile_prefix_chars=None, \ + argument_default=None, conflict_handler='error', \ + add_help=True) Create a new :class:`ArgumentParser` object. Each parameter has its own more detailed description below, but in short they are: diff --git a/Doc/library/configparser.rst b/Doc/library/configparser.rst --- a/Doc/library/configparser.rst +++ b/Doc/library/configparser.rst @@ -1051,7 +1051,8 @@ *fallback*. - .. method:: items([section], raw=False, vars=None) + .. method:: items(raw=False, vars=None) + items(section, raw=False, vars=None) When *section* is not given, return a list of *section_name*, *section_proxy* pairs, including DEFAULTSECT. diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -377,7 +377,8 @@ is to be displayed. -.. function:: newwin([nlines, ncols,] begin_y, begin_x) +.. function:: newwin(begin_y, begin_x) + newwin(nlines, ncols, begin_y, begin_x) Return a new window, whose left-upper corner is at ``(begin_y, begin_x)``, and whose height/width is *nlines*/*ncols*. @@ -656,7 +657,8 @@ the following methods and attributes: -.. method:: window.addch([y, x,] ch[, attr]) +.. method:: window.addch(ch[, attr]) + window.addch(y, x, ch[, attr]) .. note:: @@ -670,13 +672,15 @@ position and attributes are the current settings for the window object. -.. method:: window.addnstr([y, x,] str, n[, attr]) +.. method:: window.addnstr(str, n[, attr]) + window.addnstr(y, x, str, n[, attr]) Paint at most *n* characters of the string *str* at ``(y, x)`` with attributes *attr*, overwriting anything previously on the display. -.. method:: window.addstr([y, x,] str[, attr]) +.. method:: window.addstr(str[, attr]) + window.addstr(y, x, str[, attr]) Paint the string *str* at ``(y, x)`` with attributes *attr*, overwriting anything previously on the display. @@ -763,7 +767,10 @@ *bs* are *horch*. The default corner characters are always used by this function. -.. method:: window.chgat([y, x, ] [num,] attr) +.. method:: window.chgat(attr) + window.chgat(num, attr) + window.chgat(y, x, attr) + window.chgat(y, x, num, attr) Set the attributes of *num* characters at the current cursor position, or at position ``(y, x)`` if supplied. If no value of *num* is given or *num* = -1, @@ -812,7 +819,8 @@ Delete the line under the cursor. All following lines are moved up by one line. -.. method:: window.derwin([nlines, ncols,] begin_y, begin_x) +.. method:: window.derwin(begin_y, begin_x) + window.derwin(nlines, ncols, begin_y, begin_x) An abbreviation for "derive window", :meth:`derwin` is the same as calling :meth:`subwin`, except that *begin_y* and *begin_x* are relative to the origin @@ -906,7 +914,8 @@ upper-left corner. -.. method:: window.hline([y, x,] ch, n) +.. method:: window.hline(ch, n) + window.hline(y, x, ch, n) Display a horizontal line starting at ``(y, x)`` with length *n* consisting of the character *ch*. @@ -940,7 +949,8 @@ the character proper, and upper bits are the attributes. -.. method:: window.insch([y, x,] ch[, attr]) +.. method:: window.insch(ch[, attr]) + window.insch(y, x, ch[, attr]) Paint character *ch* at ``(y, x)`` with attributes *attr*, moving the line from position *x* right by one character. @@ -961,7 +971,8 @@ line. -.. method:: window.insnstr([y, x,] str, n [, attr]) +.. method:: window.insnstr(str, n[, attr]) + window.insnstr(y, x, str, n[, attr]) Insert a character string (as many characters as will fit on the line) before the character under the cursor, up to *n* characters. If *n* is zero or @@ -970,7 +981,8 @@ The cursor position does not change (after moving to *y*, *x*, if specified). -.. method:: window.insstr([y, x, ] str [, attr]) +.. method:: window.insstr(str[, attr]) + window.insstr(y, x, str[, attr]) Insert a character string (as many characters as will fit on the line) before the character under the cursor. All characters to the right of the cursor are @@ -978,7 +990,8 @@ position does not change (after moving to *y*, *x*, if specified). -.. method:: window.instr([y, x] [, n]) +.. method:: window.instr([n]) + window.instr(y, x[, n]) Return a string of characters, extracted from the window starting at the current cursor position, or at *y*, *x* if specified. Attributes are stripped @@ -1153,13 +1166,15 @@ Turn on attribute *A_STANDOUT*. -.. method:: window.subpad([nlines, ncols,] begin_y, begin_x) +.. method:: window.subpad(begin_y, begin_x) + window.subpad(nlines, ncols, begin_y, begin_x) Return a sub-window, whose upper-left corner is at ``(begin_y, begin_x)``, and whose width/height is *ncols*/*nlines*. -.. method:: window.subwin([nlines, ncols,] begin_y, begin_x) +.. method:: window.subwin(begin_y, begin_x) + window.subwin(nlines, ncols, begin_y, begin_x) Return a sub-window, whose upper-left corner is at ``(begin_y, begin_x)``, and whose width/height is *ncols*/*nlines*. @@ -1216,7 +1231,8 @@ :meth:`refresh`. -.. method:: window.vline([y, x,] ch, n) +.. method:: window.vline(ch, n) + window.vline(y, x, ch, n) Display a vertical line starting at ``(y, x)`` with length *n* consisting of the character *ch*. diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -725,11 +725,16 @@ already arranged into argument tuples, see :func:`itertools.starmap`\. -.. function:: max(iterable[, args...], *[, key]) +.. function:: max(iterable, *[, key]) + max(arg1, arg2, *args[, key]) - With a single argument *iterable*, return the largest item of a non-empty - iterable (such as a string, tuple or list). With more than one argument, return - the largest of the arguments. + Return the largest item in an iterable or the largest of two or more + arguments. + + If one positional argument is provided, *iterable* must be a non-empty + iterable (such as a non-empty string, tuple or list). The largest item + in the iterable is returned. If two or more positional arguments are + provided, the largest of the positional arguments is returned. The optional keyword-only *key* argument specifies a one-argument ordering function like that used for :meth:`list.sort`. @@ -748,11 +753,16 @@ :ref:`typememoryview` for more information. -.. function:: min(iterable[, args...], *[, key]) +.. function:: min(iterable, *[, key]) + min(arg1, arg2, *args[, key]) - With a single argument *iterable*, return the smallest item of a non-empty - iterable (such as a string, tuple or list). With more than one argument, return - the smallest of the arguments. + Return the smallest item in an iterable or the smallest of two or more + arguments. + + If one positional argument is provided, *iterable* must be a non-empty + iterable (such as a non-empty string, tuple or list). The smallest item + in the iterable is returned. If two or more positional arguments are + provided, the smallest of the positional arguments is returned. The optional keyword-only *key* argument specifies a one-argument ordering function like that used for :meth:`list.sort`. @@ -970,16 +980,16 @@ must be of integer types, and *y* must be non-negative. -.. function:: print([object, ...], *, sep=' ', end='\\n', file=sys.stdout, flush=False) +.. function:: print(*objects, sep=' ', end='\\n', file=sys.stdout, flush=False) - Print *object*\(s) to the stream *file*, separated by *sep* and followed by + Print *objects* to the stream *file*, separated by *sep* and followed by *end*. *sep*, *end* and *file*, if present, must be given as keyword arguments. All non-keyword arguments are converted to strings like :func:`str` does and written to the stream, separated by *sep* and followed by *end*. Both *sep* and *end* must be strings; they can also be ``None``, which means to use the - default values. If no *object* is given, :func:`print` will just write + default values. If no *objects* are given, :func:`print` will just write *end*. The *file* argument must be an object with a ``write(string)`` method; if it @@ -1061,7 +1071,8 @@ .. _func-range: -.. function:: range([start,] stop[, step]) +.. function:: range(stop) + range(start, stop[, step]) :noindex: Rather than being a function, :class:`range` is actually an immutable @@ -1126,7 +1137,8 @@ ``x.foobar = 123``. -.. function:: slice([start,] stop[, step]) +.. function:: slice(stop) + slice(start, stop[, step]) .. index:: single: Numerical Python diff --git a/Doc/library/http.client.rst b/Doc/library/http.client.rst --- a/Doc/library/http.client.rst +++ b/Doc/library/http.client.rst @@ -27,7 +27,8 @@ The module provides the following classes: -.. class:: HTTPConnection(host, port=None[, strict[, timeout[, source_address]]]) +.. class:: HTTPConnection(host, port=None[, strict][, timeout], \ + source_address=None) An :class:`HTTPConnection` instance represents one transaction with an HTTP server. It should be instantiated passing it a host and optional port @@ -55,7 +56,10 @@ are not supported anymore. -.. class:: HTTPSConnection(host, port=None, key_file=None, cert_file=None[, strict[, timeout[, source_address]]], *, context=None, check_hostname=None) +.. class:: HTTPSConnection(host, port=None, key_file=None, \ + cert_file=None[, strict][, timeout], \ + source_address=None, *, context=None, \ + check_hostname=None) A subclass of :class:`HTTPConnection` that uses SSL for communication with secure servers. Default port is ``443``. If *context* is specified, it diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -471,7 +471,7 @@ Returns :class:`BoundArguments`, or raises a :exc:`TypeError` if the passed arguments do not match the signature. - .. method:: Signature.replace([parameters], *, [return_annotation]) + .. method:: Signature.replace(*[, parameters][, return_annotation]) Create a new Signature instance based on the instance replace was invoked on. It is possible to pass different ``parameters`` and/or @@ -565,7 +565,7 @@ ... print('Parameter:', param) Parameter: c - .. method:: Parameter.replace(*, [name], [kind], [default], [annotation]) + .. method:: Parameter.replace(*[, name][, kind][, default][, annotation]) Create a new Parameter instance based on the instance replaced was invoked on. To override a :class:`Parameter` attribute, pass the corresponding diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -401,7 +401,8 @@ self.currkey = self.keyfunc(self.currvalue) -.. function:: islice(iterable, [start,] stop [, step]) +.. function:: islice(iterable, stop) + islice(iterable, start, stop[, step]) Make an iterator that returns selected elements from the iterable. If *start* is non-zero, then elements from the iterable are skipped until start is reached. diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -295,7 +295,8 @@ :class:`Process` and exceptions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. class:: Process([group[, target[, name[, args[, kwargs]]]]], *, daemon=None) +.. class:: Process(group=None, target=None, name=None, args=(), kwargs={}, \ + *, daemon=None) Process objects represent activity that is run in a separate process. The :class:`Process` class has equivalents of all the methods of diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -273,7 +273,8 @@ strings as you like (including zero), as long as there is at least one option string overall. -The option strings passed to :meth:`add_option` are effectively labels for the +The option strings passed to :meth:`OptionParser.add_option` are effectively +labels for the option defined by that call. For brevity, we will frequently refer to *encountering an option* on the command line; in reality, :mod:`optparse` encounters *option strings* and looks up options from them. @@ -892,7 +893,8 @@ The canonical way to create an :class:`Option` instance is with the :meth:`add_option` method of :class:`OptionParser`. -.. method:: OptionParser.add_option(opt_str[, ...], attr=value, ...) +.. method:: OptionParser.add_option(option) + OptionParser.add_option(*opt_str, attr=value, ...) To define an option with only a short option string:: diff --git a/Doc/library/ossaudiodev.rst b/Doc/library/ossaudiodev.rst --- a/Doc/library/ossaudiodev.rst +++ b/Doc/library/ossaudiodev.rst @@ -67,7 +67,8 @@ ``ossaudiodev.error``.) -.. function:: open([device, ]mode) +.. function:: open(mode) + open(device, mode) Open an audio device and return an OSS audio device object. This object supports many file-like methods, such as :meth:`read`, :meth:`write`, and diff --git a/Doc/library/random.rst b/Doc/library/random.rst --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -52,20 +52,20 @@ Bookkeeping functions: -.. function:: seed([x], version=2) +.. function:: seed(a=None, version=2) Initialize the random number generator. - If *x* is omitted or ``None``, the current system time is used. If + If *a* is omitted or ``None``, the current system time is used. If randomness sources are provided by the operating system, they are used instead of the system time (see the :func:`os.urandom` function for details on availability). - If *x* is an int, it is used directly. + If *a* is an int, it is used directly. With version 2 (the default), a :class:`str`, :class:`bytes`, or :class:`bytearray` object gets converted to an :class:`int` and all of its bits are used. With version 1, - the :func:`hash` of *x* is used instead. + the :func:`hash` of *a* is used instead. .. versionchanged:: 3.2 Moved to the version 2 scheme which uses all of the bits in a string seed. @@ -93,7 +93,8 @@ Functions for integers: -.. function:: randrange([start,] stop[, step]) +.. function:: randrange(stop) + randrange(start, stop[, step]) Return a randomly selected element from ``range(start, stop, step)``. This is equivalent to ``choice(range(start, stop, step))``, but doesn't actually build a diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -1005,7 +1005,8 @@ much data, if any, was successfully sent. -.. method:: socket.sendto(bytes[, flags], address) +.. method:: socket.sendto(bytes, address) + socket.sendto(bytes, flags, address) Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by *address*. The optional *flags* diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1235,7 +1235,8 @@ commonly used for looping a specific number of times in :keyword:`for` loops. -.. class:: range([start, ]stop[, step]) +.. class:: range(stop) + range(start, stop[, step]) The arguments to the range constructor must be integers (either built-in :class:`int` or any object that implements the ``__index__`` special diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -17,7 +17,8 @@ The module defines the following functions: -.. function:: syslog([priority,] message) +.. function:: syslog(message) + syslog(priority, message) Send the string *message* to the system logger. A trailing newline is added if necessary. Each message is tagged with a priority composed of a diff --git a/Doc/library/tkinter.tix.rst b/Doc/library/tkinter.tix.rst --- a/Doc/library/tkinter.tix.rst +++ b/Doc/library/tkinter.tix.rst @@ -504,7 +504,7 @@ print(root.tix_configure()) -.. method:: tixCommand.tix_configure([cnf,] **kw) +.. method:: tixCommand.tix_configure(cnf=None, **kw) Query or modify the configuration options of the Tix application context. If no option is specified, returns a dictionary all of the available options. If -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 14 06:01:37 2012 From: python-checkins at python.org (ezio.melotti) Date: Fri, 14 Sep 2012 06:01:37 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE1ODMxOiBkb2N1?= =?utf-8?q?ment_multiple_signatures_on_different_lines=2E__Patch_by_Chris?= Message-ID: <3XJ3294zv7zQhW@mail.python.org> http://hg.python.org/cpython/rev/2291aff20a05 changeset: 79025:2291aff20a05 branch: 2.7 parent: 79022:76dd082d332e user: Ezio Melotti date: Fri Sep 14 06:48:32 2012 +0300 summary: #15831: document multiple signatures on different lines. Patch by Chris Jerdonek. files: Doc/library/argparse.rst | 9 ++- Doc/library/curses.rst | 44 ++++++++++++++------ Doc/library/functions.rst | 41 ++++++++++++------ Doc/library/itertools.rst | 3 +- Doc/library/multiprocessing.rst | 2 +- Doc/library/optparse.rst | 6 +- Doc/library/ossaudiodev.rst | 3 +- Doc/library/random.rst | 3 +- Doc/library/socket.rst | 3 +- Doc/library/syslog.rst | 3 +- Doc/library/tix.rst | 2 +- 11 files changed, 79 insertions(+), 40 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -130,9 +130,12 @@ ArgumentParser objects ---------------------- -.. class:: ArgumentParser([description], [epilog], [prog], [usage], [add_help], \ - [argument_default], [parents], [prefix_chars], \ - [conflict_handler], [formatter_class]) +.. class:: ArgumentParser(prog=None, usage=None, description=None, \ + epilog=None, parents=[], \ + formatter_class=argparse.HelpFormatter, \ + prefix_chars='-', fromfile_prefix_chars=None, \ + argument_default=None, conflict_handler='error', \ + add_help=True) Create a new :class:`ArgumentParser` object. Each parameter has its own more detailed description below, but in short they are: diff --git a/Doc/library/curses.rst b/Doc/library/curses.rst --- a/Doc/library/curses.rst +++ b/Doc/library/curses.rst @@ -380,7 +380,8 @@ is to be displayed. -.. function:: newwin([nlines, ncols,] begin_y, begin_x) +.. function:: newwin(begin_y, begin_x) + newwin(nlines, ncols, begin_y, begin_x) Return a new window, whose left-upper corner is at ``(begin_y, begin_x)``, and whose height/width is *nlines*/*ncols*. @@ -648,7 +649,8 @@ the following methods: -.. method:: window.addch([y, x,] ch[, attr]) +.. method:: window.addch(ch[, attr]) + window.addch(y, x, ch[, attr]) .. note:: @@ -662,13 +664,15 @@ position and attributes are the current settings for the window object. -.. method:: window.addnstr([y, x,] str, n[, attr]) +.. method:: window.addnstr(str, n[, attr]) + window.addnstr(y, x, str, n[, attr]) Paint at most *n* characters of the string *str* at ``(y, x)`` with attributes *attr*, overwriting anything previously on the display. -.. method:: window.addstr([y, x,] str[, attr]) +.. method:: window.addstr(str[, attr]) + window.addstr(y, x, str[, attr]) Paint the string *str* at ``(y, x)`` with attributes *attr*, overwriting anything previously on the display. @@ -755,7 +759,10 @@ *bs* are *horch*. The default corner characters are always used by this function. -.. method:: window.chgat([y, x, ] [num,] attr) +.. method:: window.chgat(attr) + window.chgat(num, attr) + window.chgat(y, x, attr) + window.chgat(y, x, num, attr) Set the attributes of *num* characters at the current cursor position, or at position ``(y, x)`` if supplied. If no value of *num* is given or *num* = -1, @@ -804,7 +811,8 @@ Delete the line under the cursor. All following lines are moved up by one line. -.. method:: window.derwin([nlines, ncols,] begin_y, begin_x) +.. method:: window.derwin(begin_y, begin_x) + window.derwin(nlines, ncols, begin_y, begin_x) An abbreviation for "derive window", :meth:`derwin` is the same as calling :meth:`subwin`, except that *begin_y* and *begin_x* are relative to the origin @@ -879,7 +887,8 @@ upper-left corner. -.. method:: window.hline([y, x,] ch, n) +.. method:: window.hline(ch, n) + window.hline(y, x, ch, n) Display a horizontal line starting at ``(y, x)`` with length *n* consisting of the character *ch*. @@ -913,7 +922,8 @@ the character proper, and upper bits are the attributes. -.. method:: window.insch([y, x,] ch[, attr]) +.. method:: window.insch(ch[, attr]) + window.insch(y, x, ch[, attr]) Paint character *ch* at ``(y, x)`` with attributes *attr*, moving the line from position *x* right by one character. @@ -934,7 +944,8 @@ line. -.. method:: window.insnstr([y, x,] str, n [, attr]) +.. method:: window.insnstr(str, n[, attr]) + window.insnstr(y, x, str, n[, attr]) Insert a character string (as many characters as will fit on the line) before the character under the cursor, up to *n* characters. If *n* is zero or @@ -943,7 +954,8 @@ The cursor position does not change (after moving to *y*, *x*, if specified). -.. method:: window.insstr([y, x, ] str [, attr]) +.. method:: window.insstr(str[, attr]) + window.insstr(y, x, str[, attr]) Insert a character string (as many characters as will fit on the line) before the character under the cursor. All characters to the right of the cursor are @@ -951,7 +963,8 @@ position does not change (after moving to *y*, *x*, if specified). -.. method:: window.instr([y, x] [, n]) +.. method:: window.instr([n]) + window.instr(y, x[, n]) Return a string of characters, extracted from the window starting at the current cursor position, or at *y*, *x* if specified. Attributes are stripped @@ -1126,13 +1139,15 @@ Turn on attribute *A_STANDOUT*. -.. method:: window.subpad([nlines, ncols,] begin_y, begin_x) +.. method:: window.subpad(begin_y, begin_x) + window.subpad(nlines, ncols, begin_y, begin_x) Return a sub-window, whose upper-left corner is at ``(begin_y, begin_x)``, and whose width/height is *ncols*/*nlines*. -.. method:: window.subwin([nlines, ncols,] begin_y, begin_x) +.. method:: window.subwin(begin_y, begin_x) + window.subwin(nlines, ncols, begin_y, begin_x) Return a sub-window, whose upper-left corner is at ``(begin_y, begin_x)``, and whose width/height is *ncols*/*nlines*. @@ -1189,7 +1204,8 @@ :meth:`refresh`. -.. method:: window.vline([y, x,] ch, n) +.. method:: window.vline(ch, n) + window.vline(y, x, ch, n) Display a vertical line starting at ``(y, x)`` with length *n* consisting of the character *ch*. diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -753,11 +753,16 @@ the result is always a list. -.. function:: max(iterable[, args...][key]) +.. function:: max(iterable[, key]) + max(arg1, arg2, *args[, key]) - With a single argument *iterable*, return the largest item of a non-empty - iterable (such as a string, tuple or list). With more than one argument, return - the largest of the arguments. + Return the largest item in an iterable or the largest of two or more + arguments. + + If one positional argument is provided, *iterable* must be a non-empty + iterable (such as a non-empty string, tuple or list). The largest item + in the iterable is returned. If two or more positional arguments are + provided, the largest of the positional arguments is returned. The optional *key* argument specifies a one-argument ordering function like that used for :meth:`list.sort`. The *key* argument, if supplied, must be in keyword @@ -774,11 +779,16 @@ :ref:`typememoryview` for more information. -.. function:: min(iterable[, args...][key]) +.. function:: min(iterable, *[, key]) + min(arg1, arg2, *args[, key]) - With a single argument *iterable*, return the smallest item of a non-empty - iterable (such as a string, tuple or list). With more than one argument, return - the smallest of the arguments. + Return the smallest item in an iterable or the smallest of two or more + arguments. + + If one positional argument is provided, *iterable* must be a non-empty + iterable (such as a non-empty string, tuple or list). The smallest item + in the iterable is returned. If two or more positional arguments are + provided, the smallest of the positional arguments is returned. The optional *key* argument specifies a one-argument ordering function like that used for :meth:`list.sort`. The *key* argument, if supplied, must be in keyword @@ -918,16 +928,16 @@ accidents.) -.. function:: print([object, ...], sep=' ', end='\\n', file=sys.stdout) +.. function:: print(*objects, sep=' ', end='\\n', file=sys.stdout) - Print *object*\(s) to the stream *file*, separated by *sep* and followed by + Print *objects* to the stream *file*, separated by *sep* and followed by *end*. *sep*, *end* and *file*, if present, must be given as keyword arguments. All non-keyword arguments are converted to strings like :func:`str` does and written to the stream, separated by *sep* and followed by *end*. Both *sep* and *end* must be strings; they can also be ``None``, which means to use the - default values. If no *object* is given, :func:`print` will just write + default values. If no *objects* are given, :func:`print` will just write *end*. The *file* argument must be an object with a ``write(string)`` method; if it @@ -1025,7 +1035,8 @@ The ``getter``, ``setter``, and ``deleter`` attributes were added. -.. function:: range([start,] stop[, step]) +.. function:: range(stop) + range(start, stop[, step]) This is a versatile function to create lists containing arithmetic progressions. It is most often used in :keyword:`for` loops. The arguments must be plain @@ -1221,7 +1232,8 @@ ``x.foobar = 123``. -.. function:: slice([start,] stop[, step]) +.. function:: slice(stop) + slice(start, stop[, step]) .. index:: single: Numerical Python @@ -1497,7 +1509,8 @@ dictionary are ignored. -.. function:: xrange([start,] stop[, step]) +.. function:: xrange(stop) + xrange(start, stop[, step]) This function is very similar to :func:`range`, but returns an "xrange object" instead of a list. This is an opaque sequence type which yields the same values diff --git a/Doc/library/itertools.rst b/Doc/library/itertools.rst --- a/Doc/library/itertools.rst +++ b/Doc/library/itertools.rst @@ -393,7 +393,8 @@ yield function(*args) -.. function:: islice(iterable, [start,] stop [, step]) +.. function:: islice(iterable, stop) + islice(iterable, start, stop[, step]) Make an iterator that returns selected elements from the iterable. If *start* is non-zero, then elements from the iterable are skipped until start is reached. diff --git a/Doc/library/multiprocessing.rst b/Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst +++ b/Doc/library/multiprocessing.rst @@ -298,7 +298,7 @@ :class:`Process` and exceptions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. class:: Process([group[, target[, name[, args[, kwargs]]]]]) +.. class:: Process(group=None, target=None, name=None, args=(), kwargs={}) Process objects represent activity that is run in a separate process. The :class:`Process` class has equivalents of all the methods of diff --git a/Doc/library/optparse.rst b/Doc/library/optparse.rst --- a/Doc/library/optparse.rst +++ b/Doc/library/optparse.rst @@ -275,7 +275,8 @@ strings as you like (including zero), as long as there is at least one option string overall. -The option strings passed to :meth:`add_option` are effectively labels for the +The option strings passed to :meth:`OptionParser.add_option` are effectively +labels for the option defined by that call. For brevity, we will frequently refer to *encountering an option* on the command line; in reality, :mod:`optparse` encounters *option strings* and looks up options from them. @@ -895,7 +896,8 @@ The canonical way to create an :class:`Option` instance is with the :meth:`add_option` method of :class:`OptionParser`. -.. method:: OptionParser.add_option(opt_str[, ...], attr=value, ...) +.. method:: OptionParser.add_option(option) + OptionParser.add_option(*opt_str, attr=value, ...) To define an option with only a short option string:: diff --git a/Doc/library/ossaudiodev.rst b/Doc/library/ossaudiodev.rst --- a/Doc/library/ossaudiodev.rst +++ b/Doc/library/ossaudiodev.rst @@ -66,7 +66,8 @@ ``ossaudiodev.error``.) -.. function:: open([device, ]mode) +.. function:: open(mode) + open(device, mode) Open an audio device and return an OSS audio device object. This object supports many file-like methods, such as :meth:`read`, :meth:`write`, and diff --git a/Doc/library/random.rst b/Doc/library/random.rst --- a/Doc/library/random.rst +++ b/Doc/library/random.rst @@ -124,7 +124,8 @@ Functions for integers: -.. function:: randrange([start,] stop[, step]) +.. function:: randrange(stop) + randrange(start, stop[, step]) Return a randomly selected element from ``range(start, stop, step)``. This is equivalent to ``choice(range(start, stop, step))``, but doesn't actually build a diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -739,7 +739,8 @@ much data, if any, was successfully sent. -.. method:: socket.sendto(string[, flags], address) +.. method:: socket.sendto(string, address) + socket.sendto(string, flags, address) Send data to the socket. The socket should not be connected to a remote socket, since the destination socket is specified by *address*. The optional *flags* diff --git a/Doc/library/syslog.rst b/Doc/library/syslog.rst --- a/Doc/library/syslog.rst +++ b/Doc/library/syslog.rst @@ -17,7 +17,8 @@ The module defines the following functions: -.. function:: syslog([priority,] message) +.. function:: syslog(message) + syslog(priority, message) Send the string *message* to the system logger. A trailing newline is added if necessary. Each message is tagged with a priority composed of a diff --git a/Doc/library/tix.rst b/Doc/library/tix.rst --- a/Doc/library/tix.rst +++ b/Doc/library/tix.rst @@ -514,7 +514,7 @@ print root.tix_configure() -.. method:: tixCommand.tix_configure([cnf,] **kw) +.. method:: tixCommand.tix_configure(cnf=None **kw) Query or modify the configuration options of the Tix application context. If no option is specified, returns a dictionary all of the available options. If -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Fri Sep 14 06:05:58 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 14 Sep 2012 06:05:58 +0200 Subject: [Python-checkins] Daily reference leaks (2b4a89f82485): sum=0 Message-ID: results for 2b4a89f82485 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogRmaFc3', '-x'] From python-checkins at python.org Fri Sep 14 17:34:18 2012 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 14 Sep 2012 17:34:18 +0200 (CEST) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1ODQy?= =?utf-8?q?=3A_the_SocketIO=2E=7Breadable=2Cwritable=2Cseekable=7D_methods?= =?utf-8?q?_now_raise?= Message-ID: <3XJLPQ06Q3zLw8@mail.python.org> http://hg.python.org/cpython/rev/fad797916266 changeset: 79026:fad797916266 branch: 3.2 parent: 79023:b01eb870f84f user: Antoine Pitrou date: Fri Sep 14 17:28:10 2012 +0200 summary: Issue #15842: the SocketIO.{readable,writable,seekable} methods now raise ValueError when the file-like object is closed. Patch by Alessandro Moura. files: Lib/socket.py | 15 +++++++++++++-- Lib/test/test_socket.py | 11 +++++++++++ Misc/NEWS | 4 ++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -315,12 +315,23 @@ def readable(self): """True if the SocketIO is open for reading. """ - return self._reading and not self.closed + if self.closed: + raise ValueError("I/O operation on closed socket.") + return self._reading def writable(self): """True if the SocketIO is open for writing. """ - return self._writing and not self.closed + if self.closed: + raise ValueError("I/O operation on closed socket.") + return self._writing + + def seekable(self): + """True if the SocketIO is open for seeking. + """ + if self.closed: + raise ValueError("I/O operation on closed socket.") + return super().seekable() def fileno(self): """Return the file descriptor of the underlying socket. diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -839,6 +839,17 @@ fp.close() self.assertEqual(repr(fp), "<_io.BufferedReader name=-1>") + def test_unusable_closed_socketio(self): + with socket.socket() as sock: + fp = sock.makefile("rb", buffering=0) + self.assertTrue(fp.readable()) + self.assertFalse(fp.writable()) + self.assertFalse(fp.seekable()) + fp.close() + self.assertRaises(ValueError, fp.readable) + self.assertRaises(ValueError, fp.writable) + self.assertRaises(ValueError, fp.seekable) + def testListenBacklog0(self): srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM) srv.bind((HOST, 0)) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -120,6 +120,10 @@ Library ------- +- Issue #15842: the SocketIO.{readable,writable,seekable} methods now + raise ValueError when the file-like object is closed. Patch by Alessandro + Moura. + - Issue #15881: Fixed atexit hook in multiprocessing. Original patch by Chris McDonough. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Sep 14 17:34:19 2012 From: python-checkins at python.org (antoine.pitrou) Date: Fri, 14 Sep 2012 17:34:19 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315842=3A_the_SocketIO=2E=7Breadable=2Cwritable?= =?utf-8?q?=2Cseekable=7D_methods_now_raise?= Message-ID: <3XJLPR4YZ4zQ4v@mail.python.org> http://hg.python.org/cpython/rev/3b0e20f71d8a changeset: 79027:3b0e20f71d8a parent: 79024:0ed61ee823d8 parent: 79026:fad797916266 user: Antoine Pitrou date: Fri Sep 14 17:30:31 2012 +0200 summary: Issue #15842: the SocketIO.{readable,writable,seekable} methods now raise ValueError when the file-like object is closed. Patch by Alessandro Moura. files: Lib/socket.py | 15 +++++++++++++-- Lib/test/test_socket.py | 11 +++++++++++ Misc/NEWS | 4 ++++ 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py --- a/Lib/socket.py +++ b/Lib/socket.py @@ -324,12 +324,23 @@ def readable(self): """True if the SocketIO is open for reading. """ - return self._reading and not self.closed + if self.closed: + raise ValueError("I/O operation on closed socket.") + return self._reading def writable(self): """True if the SocketIO is open for writing. """ - return self._writing and not self.closed + if self.closed: + raise ValueError("I/O operation on closed socket.") + return self._writing + + def seekable(self): + """True if the SocketIO is open for seeking. + """ + if self.closed: + raise ValueError("I/O operation on closed socket.") + return super().seekable() def fileno(self): """Return the file descriptor of the underlying socket. diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1245,6 +1245,17 @@ fp.close() self.assertEqual(repr(fp), "<_io.BufferedReader name=-1>") + def test_unusable_closed_socketio(self): + with socket.socket() as sock: + fp = sock.makefile("rb", buffering=0) + self.assertTrue(fp.readable()) + self.assertFalse(fp.writable()) + self.assertFalse(fp.seekable()) + fp.close() + self.assertRaises(ValueError, fp.readable) + self.assertRaises(ValueError, fp.writable) + self.assertRaises(ValueError, fp.seekable) + def test_pickle(self): sock = socket.socket() with sock: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -29,6 +29,10 @@ Library ------- +- Issue #15842: the SocketIO.{readable,writable,seekable} methods now + raise ValueError when the file-like object is closed. Patch by Alessandro + Moura. + - Issue #15882: Change _decimal to accept any coefficient tuple when constructing infinities. This is done for backwards compatibility with decimal.py: Infinity coefficients are undefined in _decimal -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Sep 15 00:12:07 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:07 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Port_PyPy=27s_chaos_ben?= =?utf-8?q?chmark=2E?= Message-ID: <3XJWDR1m2yzQ6B@mail.python.org> http://hg.python.org/benchmarks/rev/853737d363da changeset: 165:853737d363da user: Brett Cannon date: Fri Sep 14 10:23:19 2012 -0400 summary: Port PyPy's chaos benchmark. files: perf.py | 12 +- performance/bm_chaos.py | 264 ++++++++++++++++++++++++++++ 2 files changed, 274 insertions(+), 2 deletions(-) diff --git a/perf.py b/perf.py --- a/perf.py +++ b/perf.py @@ -1614,10 +1614,18 @@ bm_path = Relative("performance/bm_nqueens.py") return MeasureGeneric(python, options, bm_path) - def BM_NQueens(*args, **kwargs): return SimpleBenchmark(MeasureNQueens, *args, **kwargs) + +def MeasureChaos(python, options): + bm_path = Relative("performance/bm_chaos.py") + return MeasureGeneric(python, options, bm_path, iteration_scaling=1) + +def BM_Chaos(*args, **kwargs): + return SimpleBenchmark(MeasureChaos, *args, **kwargs) + + def MeasureLogging(python, options, extra_args): """Test the performance of Python's logging module. @@ -2004,7 +2012,7 @@ "template" : ["slowspitfire", "django", "mako"], "logging": ["silent_logging", "simple_logging", "formatted_logging"], # Benchmarks natively 2.x- and 3.x-compatible - "2n3": ["calls", "math", "fastpickle", "fastunpickle", + "2n3": ["calls", "chaos", "math", "fastpickle", "fastunpickle", "json_dump", "json_load", "regex", "threading", "nqueens", "unpack_sequence", "richards", "logging", "normal_startup", "startup_nosite", diff --git a/performance/bm_chaos.py b/performance/bm_chaos.py new file mode 100644 --- /dev/null +++ b/performance/bm_chaos.py @@ -0,0 +1,264 @@ +# Copyright (C) 2005 Carl Friedrich Bolz + +"""create chaosgame-like fractals +""" + +from __future__ import division + +import operator +import optparse +import random +random.seed(1234) +import math +import os +import sys +import time + +from compat import print_, reduce, xrange + +class GVector(object): + def __init__(self, x = 0, y = 0, z = 0): + self.x = x + self.y = y + self.z = z + + def Mag(self): + return math.sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) + + def dist(self, other): + return math.sqrt((self.x - other.x) ** 2 + + (self.y - other.y) ** 2 + + (self.z - other.z) ** 2) + + def __add__(self, other): + if not isinstance(other, GVector): + raise ValueError("Can't add GVector to " + str(type(other))) + v = GVector(self.x + other.x, self.y + other.y, self.z + other.z) + return v + + def __sub__(self, other): + return self + other * -1 + + def __mul__(self, other): + v = GVector(self.x * other, self.y * other, self.z * other) + return v + __rmul__ = __mul__ + + def linear_combination(self, other, l1, l2=None): + if l2 is None: + l2 = 1 - l1 + v = GVector(self.x * l1 + other.x * l2, + self.y * l1 + other.y * l2, + self.z * l1 + other.z * l2) + return v + + + def __str__(self): + return "<%f, %f, %f>" % (self.x, self.y, self.z) + + def __repr__(self): + return "GVector(%f, %f, %f)" % (self.x, self.y, self.z) + +def GetKnots(points, degree): + knots = [0] * degree + range(1, len(points) - degree) + knots += [len(points) - degree] * degree + return knots + +class Spline(object): + """Class for representing B-Splines and NURBS of arbitrary degree""" + def __init__(self, points, degree = 3, knots = None): + """Creates a Spline. points is a list of GVector, degree is the +degree of the Spline.""" + if knots == None: + self.knots = GetKnots(points, degree) + else: + if len(points) > len(knots) - degree + 1: + raise ValueError("too many control points") + elif len(points) < len(knots) - degree + 1: + raise ValueError("not enough control points") + last = knots[0] + for cur in knots[1:]: + if cur < last: + raise ValueError("knots not strictly increasing") + last = cur + self.knots = knots + self.points = points + self.degree = degree + + def GetDomain(self): + """Returns the domain of the B-Spline""" + return (self.knots[self.degree - 1], + self.knots[len(self.knots) - self.degree]) + + def __call__(self, u): + """Calculates a point of the B-Spline using de Boors Algorithm""" + dom = self.GetDomain() + if u < dom[0] or u > dom[1]: + raise ValueError("Function value not in domain") + if u == dom[0]: + return self.points[0] + if u == dom[1]: + return self.points[-1] + I = self.GetIndex(u) + d = [self.points[I - self.degree + 1 + ii] + for ii in range(self.degree + 1)] + U = self.knots + for ik in range(1, self.degree + 1): + for ii in range(I - self.degree + ik + 1, I + 2): + ua = U[ii + self.degree - ik] + ub = U[ii - 1] + co1 = (ua - u) / (ua - ub) + co2 = (u - ub) / (ua - ub) + index = ii - I + self.degree - ik - 1 + d[index] = d[index].linear_combination(d[index + 1], co1, co2) + return d[0] + + def GetIndex(self, u): + dom = self.GetDomain() + for ii in range(self.degree - 1, len(self.knots) - self.degree): + if u >= self.knots[ii] and u < self.knots[ii + 1]: + I = ii + break + else: + I = dom[1] - 1 + return I + + def __len__(self): + return len(self.points) + + def __repr__(self): + return "Spline(%r, %r, %r)" % (self.points, self.degree, self.knots) + + +class Chaosgame(object): + def __init__(self, splines, thickness=0.1): + self.splines = splines + self.thickness = thickness + self.minx = min([p.x for spl in splines for p in spl.points]) + self.miny = min([p.y for spl in splines for p in spl.points]) + self.maxx = max([p.x for spl in splines for p in spl.points]) + self.maxy = max([p.y for spl in splines for p in spl.points]) + self.height = self.maxy - self.miny + self.width = self.maxx - self.minx + self.num_trafos = [] + maxlength = thickness * self.width / self.height + for spl in splines: + length = 0 + curr = spl(0) + for i in range(1, 1000): + last = curr + t = 1 / 999 * i + curr = spl(t) + length += curr.dist(last) + self.num_trafos.append(max(1, int(length / maxlength * 1.5))) + self.num_total = reduce(operator.add, self.num_trafos, 0) + + + def get_random_trafo(self): + r = random.randrange(int(self.num_total) + 1) + l = 0 + for i in range(len(self.num_trafos)): + if r >= l and r < l + self.num_trafos[i]: + return i, random.randrange(self.num_trafos[i]) + l += self.num_trafos[i] + return len(self.num_trafos) - 1, random.randrange(self.num_trafos[-1]) + + def transform_point(self, point, trafo=None): + x = (point.x - self.minx) / self.width + y = (point.y - self.miny) / self.height + if trafo is None: + trafo = self.get_random_trafo() + start, end = self.splines[trafo[0]].GetDomain() + length = end - start + seg_length = length / self.num_trafos[trafo[0]] + t = start + seg_length * trafo[1] + seg_length * x + basepoint = self.splines[trafo[0]](t) + if t + 1/50000 > end: + neighbour = self.splines[trafo[0]](t - 1/50000) + derivative = neighbour - basepoint + else: + neighbour = self.splines[trafo[0]](t + 1/50000) + derivative = basepoint - neighbour + if derivative.Mag() != 0: + basepoint.x += derivative.y / derivative.Mag() * (y - 0.5) * \ + self.thickness + basepoint.y += -derivative.x / derivative.Mag() * (y - 0.5) * \ + self.thickness + else: + print_("r", end='') + self.truncate(basepoint) + return basepoint + + def truncate(self, point): + if point.x >= self.maxx: + point.x = self.maxx + if point.y >= self.maxy: + point.y = self.maxy + if point.x < self.minx: + point.x = self.minx + if point.y < self.miny: + point.y = self.miny + + def create_image_chaos(self, w, h, n): + im = [[1] * h for i in range(w)] + point = GVector((self.maxx + self.minx) / 2, + (self.maxy + self.miny) / 2, 0) + colored = 0 + times = [] + for _ in range(n): + t1 = time.time() + for i in xrange(5000): + point = self.transform_point(point) + x = (point.x - self.minx) / self.width * w + y = (point.y - self.miny) / self.height * h + x = int(x) + y = int(y) + if x == w: + x -= 1 + if y == h: + y -= 1 + im[x][h - y - 1] = 0 + t2 = time.time() + times.append(t2 - t1) + return times + + +def main(n): + splines = [ + Spline([ + GVector(1.597350, 3.304460, 0.000000), + GVector(1.575810, 4.123260, 0.000000), + GVector(1.313210, 5.288350, 0.000000), + GVector(1.618900, 5.329910, 0.000000), + GVector(2.889940, 5.502700, 0.000000), + GVector(2.373060, 4.381830, 0.000000), + GVector(1.662000, 4.360280, 0.000000)], + 3, [0, 0, 0, 1, 1, 1, 2, 2, 2]), + Spline([ + GVector(2.804500, 4.017350, 0.000000), + GVector(2.550500, 3.525230, 0.000000), + GVector(1.979010, 2.620360, 0.000000), + GVector(1.979010, 2.620360, 0.000000)], + 3, [0, 0, 0, 1, 1, 1]), + Spline([ + GVector(2.001670, 4.011320, 0.000000), + GVector(2.335040, 3.312830, 0.000000), + GVector(2.366800, 3.233460, 0.000000), + GVector(2.366800, 3.233460, 0.000000)], + 3, [0, 0, 0, 1, 1, 1]) + ] + c = Chaosgame(splines, 0.25) + return c.create_image_chaos(1000, 1200, n) + + + +if __name__ == "__main__": + import util + parser = optparse.OptionParser( + usage="%prog [options]", + description="Test the performance of the Chaos benchmark") + util.add_standard_options_to(parser) + options, args = parser.parse_args() + + util.run_benchmark(options, options.num_runs, main) + -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 15 00:12:08 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:08 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Remove_dead_file=2E?= Message-ID: <3XJWDS3yrbzQCt@mail.python.org> http://hg.python.org/benchmarks/rev/29b7da4ef90b changeset: 166:29b7da4ef90b user: Brett Cannon date: Fri Sep 14 10:23:45 2012 -0400 summary: Remove dead file. files: performance/test_bm_ai.py | 31 --------------------------- 1 files changed, 0 insertions(+), 31 deletions(-) diff --git a/performance/test_bm_ai.py b/performance/test_bm_ai.py deleted file mode 100644 --- a/performance/test_bm_ai.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env python - -"""Brief tests for bm_ai.py""" - -__author__ = "collinwinter at google.com (Collin Winter)" - -# Python imports -import unittest - -# Local imports -import bm_ai - - -class AiTests(unittest.TestCase): - - def test_permutations(self): - result = set(bm_ai.permutations(range(3), 2)) - correct = set([(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]) - self.assertEqual(result, correct) - - def test_alphametics(self): - result = set(bm_ai.alphametics("ABAB + BABA == CCCC")) - self.assertTrue("2727 + 7272 == 9999" in result, result) - - def test_n_queens(self): - result = set(bm_ai.n_queens(4)) - correct = set([(1, 3, 0, 2), (2, 0, 3, 1)]) - self.assertEqual(result, correct) - -if __name__ == "__main__": - unittest.main() -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 15 00:12:09 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:09 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Port_PyPy=27s_fannkuch_?= =?utf-8?q?benchmark=2E?= Message-ID: <3XJWDT6XLczQNT@mail.python.org> http://hg.python.org/benchmarks/rev/5ebfddd6a81e changeset: 167:5ebfddd6a81e user: Brett Cannon date: Fri Sep 14 10:49:27 2012 -0400 summary: Port PyPy's fannkuch benchmark. files: perf.py | 10 +++- performance/bm_fannkuch.py | 72 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletions(-) diff --git a/perf.py b/perf.py --- a/perf.py +++ b/perf.py @@ -1626,6 +1626,14 @@ return SimpleBenchmark(MeasureChaos, *args, **kwargs) +def MeasureFannkuch(python, options): + bm_path = Relative("performance/bm_fannkuch.py") + return MeasureGeneric(python, options, bm_path, iteration_scaling=1) + +def BM_Fannkuch(*args, **kwargs): + return SimpleBenchmark(MeasureChaos, *args, **kwargs) + + def MeasureLogging(python, options, extra_args): """Test the performance of Python's logging module. @@ -2016,7 +2024,7 @@ "json_dump", "json_load", "regex", "threading", "nqueens", "unpack_sequence", "richards", "logging", "normal_startup", "startup_nosite", - "pathlib"], + "pathlib", "fannkuch"], # After 2to3-conversion "py3k": ["2to3", "2n3", "mako"] } diff --git a/performance/bm_fannkuch.py b/performance/bm_fannkuch.py new file mode 100644 --- /dev/null +++ b/performance/bm_fannkuch.py @@ -0,0 +1,72 @@ +# -*- coding: utf-8 -*- +# The Computer Language Benchmarks Game +# http://shootout.alioth.debian.org/ +# +# contributed by Sokolov Yura +# modified by Tupteq + +from compat import xrange +import optparse +import time +import util + +def fannkuch(n): + count = list(range(1, n+1)) + max_flips = 0 + m = n-1 + r = n + check = 0 + perm1 = list(range(n)) + perm = list(range(n)) + perm1_ins = perm1.insert + perm1_pop = perm1.pop + + while 1: + if check < 30: + #print "".join(str(i+1) for i in perm1) + check += 1 + + while r != 1: + count[r-1] = r + r -= 1 + + if perm1[0] != 0 and perm1[m] != m: + perm = perm1[:] + flips_count = 0 + k = perm[0] + while k: + perm[:k+1] = perm[k::-1] + flips_count += 1 + k = perm[0] + + if flips_count > max_flips: + max_flips = flips_count + + while r != n: + perm1_ins(r, perm1_pop(0)) + count[r] -= 1 + if count[r] > 0: + break + r += 1 + else: + return max_flips + +DEFAULT_ARG = 9 + +def main(n): + times = [] + for i in range(n): + t0 = time.time() + fannkuch(DEFAULT_ARG) + tk = time.time() + times.append(tk - t0) + return times + +if __name__ == "__main__": + parser = optparse.OptionParser( + usage="%prog [options]", + description="Test the performance of the Float benchmark") + util.add_standard_options_to(parser) + options, args = parser.parse_args() + + util.run_benchmark(options, options.num_runs, main) -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 15 00:12:11 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:11 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Tweak_import_order_to_f?= =?utf-8?q?ollow_style_of_other_modules=2E?= Message-ID: <3XJWDW1dcNzQVk@mail.python.org> http://hg.python.org/benchmarks/rev/55f65f914a65 changeset: 168:55f65f914a65 user: Brett Cannon date: Fri Sep 14 10:52:12 2012 -0400 summary: Tweak import order to follow style of other modules. files: performance/bm_fannkuch.py | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/performance/bm_fannkuch.py b/performance/bm_fannkuch.py --- a/performance/bm_fannkuch.py +++ b/performance/bm_fannkuch.py @@ -1,15 +1,16 @@ -# -*- coding: utf-8 -*- # The Computer Language Benchmarks Game # http://shootout.alioth.debian.org/ # # contributed by Sokolov Yura # modified by Tupteq -from compat import xrange import optparse import time import util +from compat import xrange + + def fannkuch(n): count = list(range(1, n+1)) max_flips = 0 -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 15 00:12:12 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:12 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Port_PyPy=27s_float_ben?= =?utf-8?q?chmark=2E?= Message-ID: <3XJWDX3tw3zQHY@mail.python.org> http://hg.python.org/benchmarks/rev/21dbe371dfdc changeset: 169:21dbe371dfdc user: Brett Cannon date: Fri Sep 14 10:54:44 2012 -0400 summary: Port PyPy's float benchmark. files: performance/bm_float.py | 81 ++++++++++++---------------- 1 files changed, 35 insertions(+), 46 deletions(-) diff --git a/performance/bm_float.py b/performance/bm_float.py --- a/performance/bm_float.py +++ b/performance/bm_float.py @@ -1,79 +1,68 @@ -#! /usr/bin/env python +from compat import xrange +import util -""" -Semi-micro benchmark for floating point performance. - -This is a Python implementation of a floating point benchmark originally on the -Factor language blog: -http://factor-language.blogspot.com/2009/08/performance-comparison-between-factor.html - -Local changes: -- Reduced the number of points from 5000000 to 20000. This reduces individual - iteration times, but we compensate by increasing the number of iterations. -""" - -__author__ = "alex.gaynor at gmail.com (Alex Gaynor)" - -# Python imports +from math import sin, cos, sqrt import optparse import time -from math import sin, cos, sqrt - -# Local imports -import util -from compat import xrange, next - class Point(object): + def __init__(self, i): self.x = x = sin(i) self.y = cos(i) * 3 self.z = (x * x) / 2 + def __repr__(self): + return "" % (self.x, self.y, self.z) + def normalize(self): - norm = sqrt(self.x ** 2 + self.y ** 2 + self.z ** 2) - self.x = self.x / norm - self.y = self.y / norm - self.z = self.z / norm + x = self.x + y = self.y + z = self.z + norm = sqrt(x * x + y * y + z * z) + self.x /= norm + self.y /= norm + self.z /= norm def maximize(self, other): self.x = self.x if self.x > other.x else other.x self.y = self.y if self.y > other.y else other.y self.z = self.z if self.z > other.z else other.z + return self def maximize(points): - points = iter(points) - cur = next(points) - for p in points: - cur.maximize(p) - return cur + next = points[0] + for p in points[1:]: + next = next.maximize(p) + return next - -def benchmark(): - points = [] - for i in xrange(20000): - points.append(Point(i)) +def benchmark(n): + points = [None] * n + for i in xrange(n): + points[i] = Point(i) for p in points: p.normalize() - maximize(points) + return maximize(points) +POINTS = 100000 -def test_float(count): +def main(arg): + # XXX warmup + times = [] - for _ in xrange(count): + for i in xrange(arg): t0 = time.time() - benchmark() - t1 = time.time() - times.append(t1 - t0) + o = benchmark(POINTS) + tk = time.time() + times.append(tk - t0) return times - - + if __name__ == "__main__": parser = optparse.OptionParser( usage="%prog [options]", - description="Test the performance of various floating point ops") + description="Test the performance of the Float benchmark") util.add_standard_options_to(parser) options, args = parser.parse_args() - util.run_benchmark(options, options.num_runs, test_float) + util.run_benchmark(options, options.num_runs, main) -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 15 00:12:14 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:14 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Port_PyPy=27s_meteor-co?= =?utf-8?q?ntest_benchmark=2E?= Message-ID: <3XJWDZ09MQzQDx@mail.python.org> http://hg.python.org/benchmarks/rev/4a1cb20b9560 changeset: 170:4a1cb20b9560 user: Brett Cannon date: Fri Sep 14 11:01:08 2012 -0400 summary: Port PyPy's meteor-contest benchmark. files: perf.py | 12 +- performance/bm_meteor_contest.py | 161 +++++++++++++++++++ 2 files changed, 171 insertions(+), 2 deletions(-) diff --git a/perf.py b/perf.py --- a/perf.py +++ b/perf.py @@ -1344,7 +1344,7 @@ def MeasureFloat(python, options): bm_path = Relative("performance/bm_float.py") - return MeasureGeneric(python, options, bm_path, iteration_scaling=5) + return MeasureGeneric(python, options, bm_path, iteration_scaling=1) def BM_Float(*args, **kwargs): return SimpleBenchmark(MeasureFloat, *args, **kwargs) @@ -1634,6 +1634,14 @@ return SimpleBenchmark(MeasureChaos, *args, **kwargs) +def MeasureMeteor_Contest(python, options): + bm_path = Relative("performance/bm_meteor_contest.py") + return MeasureGeneric(python, options, bm_path, iteration_scaling=1) + +def BM_Meteor_Contest(*args, **kwargs): + return SimpleBenchmark(MeasureChaos, *args, **kwargs) + + def MeasureLogging(python, options, extra_args): """Test the performance of Python's logging module. @@ -2024,7 +2032,7 @@ "json_dump", "json_load", "regex", "threading", "nqueens", "unpack_sequence", "richards", "logging", "normal_startup", "startup_nosite", - "pathlib", "fannkuch"], + "pathlib", "fannkuch", "meteor_contest"], # After 2to3-conversion "py3k": ["2to3", "2n3", "mako"] } diff --git a/performance/bm_meteor_contest.py b/performance/bm_meteor_contest.py new file mode 100644 --- /dev/null +++ b/performance/bm_meteor_contest.py @@ -0,0 +1,161 @@ +# The Computer Language Benchmarks Game +# http://shootout.alioth.debian.org/ +# +# contributed by Daniel Nanz, 2008-08-21 + +import optparse +import sys +import time +from bisect import bisect + +from compat import xrange +import util + +w, h = 5, 10 +dir_no = 6 +S, E = w * h, 2 +SE = S + (E / 2) +SW = SE - E +W, NW, NE = -E, -SE, -SW + + +def rotate(ido, rd={E: NE, NE: NW, NW: W, W: SW, SW: SE, SE: E}): + return [rd[o] for o in ido] + +def flip(ido, fd={E: E, NE: SE, NW: SW, W: W, SW: NW, SE: NE}): + return [fd[o] for o in ido] + + +def permute(ido, r_ido, rotate=rotate, flip=flip): + + ps = [ido] + for r in xrange(dir_no - 1): + ps.append(rotate(ps[-1])) + if ido == r_ido: # C2-symmetry + ps = ps[0:dir_no//2] + for pp in ps[:]: + ps.append(flip(pp)) + return ps + + +def convert(ido): + '''incremental direction offsets -> "coordinate offsets" ''' + out = [0] + for o in ido: + out.append(out[-1] + o) + return list(set(out)) + + +def get_footprints(board, cti, pieces): + + fps = [[[] for p in xrange(len(pieces))] for ci in xrange(len(board))] + for c in board: + for pi, p in enumerate(pieces): + for pp in p: + fp = frozenset([cti[c + o] for o in pp if (c + o) in cti]) + if len(fp) == 5: + fps[min(fp)][pi].append(fp) + return fps + + +def get_senh(board, cti): + '''-> south-east neighborhood''' + se_nh = [] + nh = [E, SW, SE] + for c in board: + se_nh.append(frozenset([cti[c + o] for o in nh if (c + o) in cti])) + return se_nh + + +def get_puzzle(w=w, h=h): + + board = [E*x + S*y + (y%2) for y in xrange(h) for x in xrange(w)] + cti = dict((board[i], i) for i in xrange(len(board))) + + idos = [[E, E, E, SE], # incremental direction offsets + [SE, SW, W, SW], + [W, W, SW, SE], + [E, E, SW, SE], + [NW, W, NW, SE, SW], + [E, E, NE, W], + [NW, NE, NE, W], + [NE, SE, E, NE], + [SE, SE, E, SE], + [E, NW, NW, NW]] + + perms = (permute(p, idos[3]) for p in idos) # restrict piece 4 + pieces = [[convert(pp) for pp in p] for p in perms] + return (board, cti, pieces) + + +def print_board(board, w=w, h=h): + + for y in xrange(h): + for x in xrange(w): + print(board[x + y * w]) + print('') + if y % 2 == 0: + print('') + print() + + +board, cti, pieces = get_puzzle() +fps = get_footprints(board, cti, pieces) +se_nh = get_senh(board, cti) + + +def solve(n, i_min, free, curr_board, pieces_left, solutions, + fps=fps, se_nh=se_nh, bisect=bisect): + fp_i_cands = fps[i_min] + for p in pieces_left: + fp_cands = fp_i_cands[p] + for fp in fp_cands: + if fp <= free: + n_curr_board = curr_board[:] + for ci in fp: + n_curr_board[ci] = p + if len(pieces_left) > 1: + n_free = free - fp + n_i_min = min(n_free) + if len(n_free & se_nh[n_i_min]) > 0: + n_pieces_left = pieces_left[:] + n_pieces_left.remove(p) + solve(n, n_i_min, n_free, n_curr_board, + n_pieces_left, solutions) + else: + s = ''.join(map(str, n_curr_board)) + solutions.insert(bisect(solutions, s), s) + rs = s[::-1] + solutions.insert(bisect(solutions, rs), rs) + if len(solutions) >= n: + return + if len(solutions) >= n: + return + return + +SOLVE_ARG = 60 + +def main(n): + times = [] + for i in xrange(n): + t0 = time.time() + free = frozenset(xrange(len(board))) + curr_board = [-1] * len(board) + pieces_left = list(range(len(pieces))) + solutions = [] + solve(SOLVE_ARG, 0, free, curr_board, pieces_left, solutions) + #print len(solutions), 'solutions found\n' + #for i in (0, -1): print_board(solutions[i]) + tk = time.time() + times.append(tk - t0) + return times + +if __name__ == "__main__": + parser = optparse.OptionParser( + usage="%prog [options]", + description="Test the performance of the Float benchmark") + util.add_standard_options_to(parser) + options, args = parser.parse_args() + + util.run_benchmark(options, options.num_runs, main) + -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 15 00:12:15 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:15 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Port_PyPy=27s_spectral?= =?utf-8?q?=5Fnorm_benchmark=2E?= Message-ID: <3XJWDb3gvMzQ6q@mail.python.org> http://hg.python.org/benchmarks/rev/0d00cf856dc8 changeset: 171:0d00cf856dc8 user: Brett Cannon date: Fri Sep 14 11:23:41 2012 -0400 summary: Port PyPy's spectral_norm benchmark. files: perf.py | 18 ++++- performance/bm_spectral_norm.py | 68 +++++++++++++++++++++ 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/perf.py b/perf.py --- a/perf.py +++ b/perf.py @@ -1641,6 +1641,13 @@ def BM_Meteor_Contest(*args, **kwargs): return SimpleBenchmark(MeasureChaos, *args, **kwargs) +def MeasureMeteor_Contest(python, options): + bm_path = Relative("performance/bm_spectral_norm.py") + return MeasureGeneric(python, options, bm_path, iteration_scaling=1) + +def BM_Spectral_Norm(*args, **kwargs): + return SimpleBenchmark(MeasureChaos, *args, **kwargs) + def MeasureLogging(python, options, extra_args): """Test the performance of Python's logging module. @@ -2028,11 +2035,12 @@ "template" : ["slowspitfire", "django", "mako"], "logging": ["silent_logging", "simple_logging", "formatted_logging"], # Benchmarks natively 2.x- and 3.x-compatible - "2n3": ["calls", "chaos", "math", "fastpickle", "fastunpickle", - "json_dump", "json_load", "regex", "threading", - "nqueens", "unpack_sequence", "richards", - "logging", "normal_startup", "startup_nosite", - "pathlib", "fannkuch", "meteor_contest"], + "2n3": ["calls", "chaos", "fannkuch", "fastpickle", + "fastunpickle", "json_dump", "json_load", "math", + "logging", "meteor_contest", "normal_startup", + "nqueens", "pathlib", "regex", "spectral_norm", + "startup_nosite", "richards", "threading", + "unpack_sequence"], # After 2to3-conversion "py3k": ["2to3", "2n3", "mako"] } diff --git a/performance/bm_spectral_norm.py b/performance/bm_spectral_norm.py new file mode 100644 --- /dev/null +++ b/performance/bm_spectral_norm.py @@ -0,0 +1,68 @@ +# The Computer Language Benchmarks Game +# http://shootout.alioth.debian.org/ +# Contributed by Sebastien Loisel +# Fixed by Isaac Gouy +# Sped up by Josh Goldfoot +# Dirtily sped up by Simon Descarpentries +# Concurrency by Jason Stitt + +from math import sqrt +import time +import itertools +import optparse + +from compat import izip, xrange +import util + +def eval_A(i, j): + return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1) + +def eval_times_u(func, u): + return map(func, ((i,u) for i in xrange(len(list(u))))) + +def eval_AtA_times_u(u): + return eval_times_u(part_At_times_u, eval_times_u(part_A_times_u, u)) + +def part_A_times_u(i_u): + i, u = i_u + partial_sum = 0 + for j, u_j in enumerate(u): + partial_sum += eval_A(i, j) * u_j + return partial_sum + +def part_At_times_u(i_u): + i, u = i_u + partial_sum = 0 + for j, u_j in enumerate(u): + partial_sum += eval_A(j, i) * u_j + return partial_sum + +DEFAULT_N = 130 + +def main(n): + times = [] + for i in xrange(n): + t0 = time.time() + u = [1] * DEFAULT_N + + for dummy in xrange(10): + v = eval_AtA_times_u(u) + u = eval_AtA_times_u(v) + + vBv = vv = 0 + + for ue, ve in izip(u, v): + vBv += ue * ve + vv += ve * ve + tk = time.time() + times.append(tk - t0) + return times + +if __name__ == "__main__": + parser = optparse.OptionParser( + usage="%prog [options]", + description="Test the performance of the Float benchmark") + util.add_standard_options_to(parser) + options, args = parser.parse_args() + + util.run_benchmark(options, options.num_runs, main) -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 15 00:12:17 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:17 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Add_the_Telco_benchmark?= =?utf-8?q?_and_fix_some_stupid_errors_in_perf=2Epy=2E?= Message-ID: <3XJWDd0HkGzQNv@mail.python.org> http://hg.python.org/benchmarks/rev/92ae96f805ce changeset: 172:92ae96f805ce user: Brett Cannon date: Fri Sep 14 11:37:08 2012 -0400 summary: Add the Telco benchmark and fix some stupid errors in perf.py. files: perf.py | 25 +++- performance/bm_telco.py | 97 +++++++++++++++++++++ performance/data/telco-bench.b | Bin 3 files changed, 114 insertions(+), 8 deletions(-) diff --git a/perf.py b/perf.py --- a/perf.py +++ b/perf.py @@ -1631,22 +1631,31 @@ return MeasureGeneric(python, options, bm_path, iteration_scaling=1) def BM_Fannkuch(*args, **kwargs): - return SimpleBenchmark(MeasureChaos, *args, **kwargs) - - -def MeasureMeteor_Contest(python, options): + return SimpleBenchmark(MeasureFannkuch, *args, **kwargs) + + +def MeasureMeteorContest(python, options): bm_path = Relative("performance/bm_meteor_contest.py") return MeasureGeneric(python, options, bm_path, iteration_scaling=1) def BM_Meteor_Contest(*args, **kwargs): - return SimpleBenchmark(MeasureChaos, *args, **kwargs) - -def MeasureMeteor_Contest(python, options): + return SimpleBenchmark(MeasureMeteorContest, *args, **kwargs) + + +def MeasureSpectralNorm(python, options): bm_path = Relative("performance/bm_spectral_norm.py") return MeasureGeneric(python, options, bm_path, iteration_scaling=1) def BM_Spectral_Norm(*args, **kwargs): - return SimpleBenchmark(MeasureChaos, *args, **kwargs) + return SimpleBenchmark(MeasureSpectralNorm, *args, **kwargs) + + +def MeasureTelco(python, options): + bm_path = Relative("performance/bm_telco.py") + return MeasureGeneric(python, options, bm_path, iteration_scaling=1) + +def BM_Telco(*args, **kwargs): + return SimpleBenchmark(MeasureTelco, *args, **kwargs) def MeasureLogging(python, options, extra_args): diff --git a/performance/bm_telco.py b/performance/bm_telco.py new file mode 100644 --- /dev/null +++ b/performance/bm_telco.py @@ -0,0 +1,97 @@ +#-*- coding: UTF-8 -*- +""" Telco Benchmark for measuring the performance of decimal calculations + +http://www2.hursley.ibm.com/decimal/telco.html +http://www2.hursley.ibm.com/decimal/telcoSpec.html + +A call type indicator, c, is set from the bottom (least significant) bit of the duration (hence c is 0 or 1). +A r, r, is determined from the call type. Those calls with c=0 have a low r: 0.0013; the remainder (?distance calls?) have a ?premium? r: 0.00894. (The rates are, very roughly, in Euros or dollarates per second.) +A price, p, for the call is then calculated (p=r*n). This is rounded to exactly 2 fractional digits using round-half-even (Banker?s round to nearest). +A basic tax, b, is calculated: b=p*0.0675 (6.75%). This is truncated to exactly 2 fractional digits (round-down), and the total basic tax variable is then incremented (sumB=sumB+b). +For distance calls: a distance tax, d, is calculated: d=p*0.0341 (3.41%). This is truncated to exactly 2 fractional digits (round-down), and then the total distance tax variable is incremented (sumD=sumD+d). +The total price, t, is calculated (t=p+b, and, if a distance call, t=t+d). +The total prices variable is incremented (sumT=sumT+t). +The total price, t, is converted to a string, s. + +""" + +import contextlib +from decimal import * +import os +from struct import unpack +import sys +from time import clock as time + +from compat import xrange + + +def rel_path(*path): + return os.path.join(os.path.dirname(__file__), *path) + +test = False + +filename = rel_path("data", "telco-bench.b") + +def run(): + getcontext().rounding = ROUND_DOWN + rates = list(map(Decimal, ('0.0013', '0.00894'))) + twodig = Decimal('0.01') + Banker = Context(rounding=ROUND_HALF_EVEN) + basictax = Decimal("0.0675") + disttax = Decimal("0.0341") + + infil = open(filename, "rb") + start = time() + + sumT = Decimal("0") # sum of total prices + sumB = Decimal("0") # sum of basic tax + sumD = Decimal("0") # sum of 'distance' tax + + with open(filename, "rb") as infil: + for i in xrange(5000): + datum = infil.read(8) + if datum == '': break + n, = unpack('>Q', datum) + + calltype = n & 1 + r = rates[calltype] + + p = Banker.quantize(r * n, twodig) + + b = p * basictax + b = b.quantize(twodig) + sumB += b + + t = p + b + + if calltype: + d = p * disttax + d = d.quantize(twodig) + sumD += d + t += d + + sumT += t + + infil.close() + end = time() + return end - start + +def main(n): + run() # warmup + times = [] + for i in xrange(n): + times.append(run()) + return times + + + +if __name__ == "__main__": + import optparse + import util + parser = optparse.OptionParser( + usage="%prog [options]", + description="Test the performance of the Telco decimal benchmark") + util.add_standard_options_to(parser) + options, args = parser.parse_args() + + util.run_benchmark(options, options.num_runs, main) diff --git a/performance/data/telco-bench.b b/performance/data/telco-bench.b new file mode 100644 index 0000000000000000000000000000000000000000..2c7085d0732e087ac33e3cc9887b88304a826ab5 GIT binary patch [stripped] -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Sat Sep 15 00:12:25 2012 From: python-checkins at python.org (brett.cannon) Date: Sat, 15 Sep 2012 00:12:25 +0200 (CEST) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Port_PyPy=27s_tweaked_b?= =?utf-8?q?m=5Fmako_benchmark_as_bm=5Fmako=5Fv2=2E?= Message-ID: <3XJWDn5ZyWzQDx@mail.python.org> http://hg.python.org/benchmarks/rev/ffd4fb31b562 changeset: 173:ffd4fb31b562 user: Brett Cannon date: Fri Sep 14 12:25:24 2012 -0400 summary: Port PyPy's tweaked bm_mako benchmark as bm_mako_v2. files: lib/mako/.hgignore | 0 lib/mako/CHANGES | 0 lib/mako/LICENSE | 0 lib/mako/MANIFEST.in | 0 lib/mako/README | 0 lib/mako/README.py3k | 0 lib/mako/distribute_setup.py | 0 lib/mako/doc/build/Makefile | 0 lib/mako/doc/build/builder/builders.py | 0 lib/mako/doc/build/builder/util.py | 0 lib/mako/doc/build/caching.rst | 0 lib/mako/doc/build/conf.py | 0 lib/mako/doc/build/defs.rst | 0 lib/mako/doc/build/filtering.rst | 0 lib/mako/doc/build/index.rst | 0 lib/mako/doc/build/inheritance.rst | 0 lib/mako/doc/build/namespaces.rst | 0 lib/mako/doc/build/runtime.rst | 0 lib/mako/doc/build/static/docs.css | 0 lib/mako/doc/build/syntax.rst | 0 lib/mako/doc/build/templates/genindex.mako | 0 lib/mako/doc/build/templates/layout.mako | 0 lib/mako/doc/build/templates/page.mako | 0 lib/mako/doc/build/templates/search.mako | 0 lib/mako/doc/build/templates/site_base.mako | 0 lib/mako/doc/build/templates/static_base.mako | 0 lib/mako/doc/build/unicode.rst | 0 lib/mako/doc/build/usage.rst | 0 lib/mako/examples/bench/basic.py | 0 lib/mako/examples/bench/basic.py.orig | 0 lib/mako/examples/bench/cheetah/footer.tmpl | 0 lib/mako/examples/bench/cheetah/header.tmpl | 0 lib/mako/examples/bench/cheetah/template.tmpl | 0 lib/mako/examples/bench/django/templates/base.html | 0 lib/mako/examples/bench/django/templates/template.html | 0 lib/mako/examples/bench/django/templatetags/bench.py | 0 lib/mako/examples/bench/genshi/base.html | 0 lib/mako/examples/bench/genshi/template.html | 0 lib/mako/examples/bench/kid/base.kid | 0 lib/mako/examples/bench/kid/template.kid | 0 lib/mako/examples/bench/mako/footer.html | 0 lib/mako/examples/bench/mako/header.html | 0 lib/mako/examples/bench/mako/template.html | 0 lib/mako/examples/bench/mako_inheritance/base.html | 0 lib/mako/examples/bench/mako_inheritance/template.html | 0 lib/mako/examples/bench/myghty/base.myt | 0 lib/mako/examples/bench/myghty/template.myt | 0 lib/mako/examples/wsgi/htdocs/index.html | 0 lib/mako/examples/wsgi/run_wsgi.py | 0 lib/mako/examples/wsgi/templates/root.html | 0 lib/mako/mako/__init__.py | 0 lib/mako/mako/_ast_util.py | 0 lib/mako/mako/ast.py | 0 lib/mako/mako/cache.py | 0 lib/mako/mako/codegen.py | 0 lib/mako/mako/exceptions.py | 0 lib/mako/mako/ext/autohandler.py | 0 lib/mako/mako/ext/babelplugin.py | 0 lib/mako/mako/ext/preprocessors.py | 0 lib/mako/mako/ext/pygmentplugin.py | 0 lib/mako/mako/ext/turbogears.py | 0 lib/mako/mako/filters.py | 0 lib/mako/mako/lexer.py | 0 lib/mako/mako/lookup.py | 0 lib/mako/mako/parsetree.py | 0 lib/mako/mako/pygen.py | 0 lib/mako/mako/pyparser.py | 0 lib/mako/mako/runtime.py | 0 lib/mako/mako/template.py | 0 lib/mako/mako/util.py | 0 lib/mako/scripts/mako-render | 0 lib/mako/setup.cfg | 0 lib/mako/setup.py | 0 lib/mako/test/__init__.py | 0 lib/mako/test/foo/test_ns.py | 0 lib/mako/test/sample_module_namespace.py | 0 lib/mako/test/templates/badbom.html | 0 lib/mako/test/templates/bom.html | 0 lib/mako/test/templates/bommagic.html | 0 lib/mako/test/templates/chs_unicode.html | 0 lib/mako/test/templates/chs_unicode_py3k.html | 0 lib/mako/test/templates/chs_utf8.html | 0 lib/mako/test/templates/crlf.html | 0 lib/mako/test/templates/foo/modtest.html.py | 0 lib/mako/test/templates/gettext.mako | 0 lib/mako/test/templates/index.html | 0 lib/mako/test/templates/internationalization.html | 0 lib/mako/test/templates/modtest.html | 0 lib/mako/test/templates/read_unicode.html | 0 lib/mako/test/templates/read_unicode_py3k.html | 0 lib/mako/test/templates/runtimeerr.html | 0 lib/mako/test/templates/runtimeerr_py3k.html | 0 lib/mako/test/templates/subdir/foo/modtest.html.py | 0 lib/mako/test/templates/subdir/incl.html | 0 lib/mako/test/templates/subdir/index.html | 0 lib/mako/test/templates/subdir/modtest.html | 0 lib/mako/test/templates/unicode.html | 0 lib/mako/test/templates/unicode_arguments.html | 0 lib/mako/test/templates/unicode_arguments_py3k.html | 0 lib/mako/test/templates/unicode_code.html | 0 lib/mako/test/templates/unicode_code_py3k.html | 0 lib/mako/test/templates/unicode_expr.html | 0 lib/mako/test/templates/unicode_expr_py3k.html | 0 lib/mako/test/templates/unicode_runtime_error.html | 0 lib/mako/test/templates/unicode_syntax_error.html | 0 lib/mako/test/test_ast.py | 0 lib/mako/test/test_babelplugin.py | 0 lib/mako/test/test_cache.py | 0 lib/mako/test/test_call.py | 0 lib/mako/test/test_decorators.py | 0 lib/mako/test/test_def.py | 0 lib/mako/test/test_exceptions.py | 0 lib/mako/test/test_filters.py | 0 lib/mako/test/test_inheritance.py | 0 lib/mako/test/test_lexer.py | 0 lib/mako/test/test_lookup.py | 0 lib/mako/test/test_lru.py | 0 lib/mako/test/test_namespace.py | 0 lib/mako/test/test_pygen.py | 0 lib/mako/test/test_template.py | 0 lib/mako/test/test_tgplugin.py | 0 lib/mako/test/util.py | 0 lib/mako-0.7.2/CHANGES | 825 ++++++ lib/mako-0.7.2/LICENSE | 20 + lib/mako-0.7.2/MANIFEST.in | 11 + lib/mako-0.7.2/Mako.egg-info/PKG-INFO | 71 + lib/mako-0.7.2/Mako.egg-info/SOURCES.txt | 171 + lib/mako-0.7.2/Mako.egg-info/dependency_links.txt | 1 + lib/mako-0.7.2/Mako.egg-info/entry_points.txt | 14 + lib/mako-0.7.2/Mako.egg-info/not-zip-safe | 1 + lib/mako-0.7.2/Mako.egg-info/requires.txt | 4 + lib/mako-0.7.2/Mako.egg-info/top_level.txt | 1 + lib/mako-0.7.2/PKG-INFO | 71 + lib/mako-0.7.2/README.rst | 52 + lib/mako-0.7.2/distribute_setup.py | 485 +++ lib/mako-0.7.2/doc/_sources/caching.txt | 393 +++ lib/mako-0.7.2/doc/_sources/defs.txt | 622 +++++ lib/mako-0.7.2/doc/_sources/filtering.txt | 344 ++ lib/mako-0.7.2/doc/_sources/index.txt | 22 + lib/mako-0.7.2/doc/_sources/inheritance.txt | 534 ++++ lib/mako-0.7.2/doc/_sources/namespaces.txt | 349 ++ lib/mako-0.7.2/doc/_sources/runtime.txt | 448 +++ lib/mako-0.7.2/doc/_sources/syntax.txt | 469 +++ lib/mako-0.7.2/doc/_sources/unicode.txt | 345 ++ lib/mako-0.7.2/doc/_sources/usage.txt | 520 ++++ lib/mako-0.7.2/doc/_static/basic.css | 540 ++++ lib/mako-0.7.2/doc/_static/comment-bright.png | Bin lib/mako-0.7.2/doc/_static/comment-close.png | Bin lib/mako-0.7.2/doc/_static/comment.png | Bin lib/mako-0.7.2/doc/_static/default.css | 256 ++ lib/mako-0.7.2/doc/_static/docs.css | 438 +++ lib/mako-0.7.2/doc/_static/doctools.js | 247 + lib/mako-0.7.2/doc/_static/down-pressed.png | Bin lib/mako-0.7.2/doc/_static/down.png | Bin lib/mako-0.7.2/doc/_static/file.png | Bin lib/mako-0.7.2/doc/_static/jquery.js | 154 + lib/mako-0.7.2/doc/_static/makoLogo.png | Bin lib/mako-0.7.2/doc/_static/minus.png | Bin lib/mako-0.7.2/doc/_static/plus.png | Bin lib/mako-0.7.2/doc/_static/pygments.css | 62 + lib/mako-0.7.2/doc/_static/searchtools.js | 560 ++++ lib/mako-0.7.2/doc/_static/sidebar.js | 151 + lib/mako-0.7.2/doc/_static/site.css | 82 + lib/mako-0.7.2/doc/_static/underscore.js | 23 + lib/mako-0.7.2/doc/_static/up-pressed.png | Bin lib/mako-0.7.2/doc/_static/up.png | Bin lib/mako-0.7.2/doc/_static/websupport.js | 808 ++++++ lib/mako-0.7.2/doc/build/Makefile | 137 + lib/mako-0.7.2/doc/build/builder/__init__.py | 0 lib/mako-0.7.2/doc/build/builder/builders.py | 97 + lib/mako-0.7.2/doc/build/builder/util.py | 12 + lib/mako-0.7.2/doc/build/caching.rst | 393 +++ lib/mako-0.7.2/doc/build/conf.py | 287 ++ lib/mako-0.7.2/doc/build/defs.rst | 622 +++++ lib/mako-0.7.2/doc/build/filtering.rst | 344 ++ lib/mako-0.7.2/doc/build/index.rst | 22 + lib/mako-0.7.2/doc/build/inheritance.rst | 534 ++++ lib/mako-0.7.2/doc/build/namespaces.rst | 349 ++ lib/mako-0.7.2/doc/build/runtime.rst | 448 +++ lib/mako-0.7.2/doc/build/static/docs.css | 438 +++ lib/mako-0.7.2/doc/build/static/makoLogo.png | Bin lib/mako-0.7.2/doc/build/static/site.css | 82 + lib/mako-0.7.2/doc/build/syntax.rst | 469 +++ lib/mako-0.7.2/doc/build/templates/base.mako | 51 + lib/mako-0.7.2/doc/build/templates/genindex.mako | 77 + lib/mako-0.7.2/doc/build/templates/layout.mako | 199 + lib/mako-0.7.2/doc/build/templates/page.mako | 2 + lib/mako-0.7.2/doc/build/templates/rtd_layout.mako | 174 + lib/mako-0.7.2/doc/build/templates/search.mako | 25 + lib/mako-0.7.2/doc/build/unicode.rst | 345 ++ lib/mako-0.7.2/doc/build/usage.rst | 520 ++++ lib/mako-0.7.2/doc/caching.html | 777 ++++++ lib/mako-0.7.2/doc/defs.html | 726 +++++ lib/mako-0.7.2/doc/filtering.html | 476 +++ lib/mako-0.7.2/doc/genindex.html | 914 +++++++ lib/mako-0.7.2/doc/index.html | 228 + lib/mako-0.7.2/doc/inheritance.html | 671 +++++ lib/mako-0.7.2/doc/namespaces.html | 647 +++++ lib/mako-0.7.2/doc/runtime.html | 708 +++++ lib/mako-0.7.2/doc/search.html | 160 + lib/mako-0.7.2/doc/searchindex.js | 1 + lib/mako-0.7.2/doc/syntax.html | 594 ++++ lib/mako-0.7.2/doc/unicode.html | 474 +++ lib/mako-0.7.2/doc/usage.html | 1055 ++++++++ lib/mako-0.7.2/examples/bench/basic.py | 191 + lib/mako-0.7.2/examples/bench/cheetah/footer.tmpl | 2 + lib/mako-0.7.2/examples/bench/cheetah/header.tmpl | 5 + lib/mako-0.7.2/examples/bench/cheetah/template.tmpl | 31 + lib/mako-0.7.2/examples/bench/django/templatetags/__init__.py | 0 lib/mako-0.7.2/examples/bench/django/templatetags/bench.py | 8 + lib/mako-0.7.2/examples/bench/kid/base.kid | 15 + lib/mako-0.7.2/examples/bench/kid/template.kid | 22 + lib/mako-0.7.2/examples/bench/myghty/base.myt | 29 + lib/mako-0.7.2/examples/bench/myghty/template.myt | 30 + lib/mako-0.7.2/examples/wsgi/run_wsgi.py | 78 + lib/mako-0.7.2/mako/__init__.py | 9 + lib/mako-0.7.2/mako/_ast_util.py | 839 ++++++ lib/mako-0.7.2/mako/ast.py | 151 + lib/mako-0.7.2/mako/cache.py | 236 + lib/mako-0.7.2/mako/codegen.py | 1209 +++++++++ lib/mako-0.7.2/mako/exceptions.py | 362 ++ lib/mako-0.7.2/mako/ext/__init__.py | 0 lib/mako-0.7.2/mako/ext/autohandler.py | 65 + lib/mako-0.7.2/mako/ext/babelplugin.py | 132 + lib/mako-0.7.2/mako/ext/beaker_cache.py | 70 + lib/mako-0.7.2/mako/ext/preprocessors.py | 20 + lib/mako-0.7.2/mako/ext/pygmentplugin.py | 122 + lib/mako-0.7.2/mako/ext/turbogears.py | 57 + lib/mako-0.7.2/mako/filters.py | 189 + lib/mako-0.7.2/mako/lexer.py | 442 +++ lib/mako-0.7.2/mako/lookup.py | 354 ++ lib/mako-0.7.2/mako/parsetree.py | 589 ++++ lib/mako-0.7.2/mako/pygen.py | 283 ++ lib/mako-0.7.2/mako/pyparser.py | 535 ++++ lib/mako-0.7.2/mako/runtime.py | 841 ++++++ lib/mako-0.7.2/mako/template.py | 650 +++++ lib/mako-0.7.2/mako/util.py | 436 +++ lib/mako-0.7.2/scripts/mako-render | 46 + lib/mako-0.7.2/setup.cfg | 5 + lib/mako-0.7.2/setup.py | 62 + lib/mako-0.7.2/test/__init__.py | 135 + lib/mako-0.7.2/test/foo/__init__.py | 0 lib/mako-0.7.2/test/foo/test_ns.py | 7 + lib/mako-0.7.2/test/sample_module_namespace.py | 7 + lib/mako-0.7.2/test/templates/badbom.html | 2 + lib/mako-0.7.2/test/templates/bom.html | 1 + lib/mako-0.7.2/test/templates/bommagic.html | 2 + lib/mako-0.7.2/test/templates/chs_unicode.html | 11 + lib/mako-0.7.2/test/templates/chs_unicode_py3k.html | 11 + lib/mako-0.7.2/test/templates/chs_utf8.html | 17 + lib/mako-0.7.2/test/templates/crlf.html | 19 + lib/mako-0.7.2/test/templates/foo/modtest.html.py | 25 + lib/mako-0.7.2/test/templates/gettext.mako | 89 + lib/mako-0.7.2/test/templates/index.html | 1 + lib/mako-0.7.2/test/templates/internationalization.html | 920 +++++++ lib/mako-0.7.2/test/templates/modtest.html | 1 + lib/mako-0.7.2/test/templates/othersubdir/foo.html | 0 lib/mako-0.7.2/test/templates/read_unicode.html | 10 + lib/mako-0.7.2/test/templates/read_unicode_py3k.html | 10 + lib/mako-0.7.2/test/templates/runtimeerr.html | 4 + lib/mako-0.7.2/test/templates/runtimeerr_py3k.html | 4 + lib/mako-0.7.2/test/templates/subdir/foo/modtest.html.py | 25 + lib/mako-0.7.2/test/templates/subdir/incl.html | 2 + lib/mako-0.7.2/test/templates/subdir/index.html | 3 + lib/mako-0.7.2/test/templates/subdir/modtest.html | 1 + lib/mako-0.7.2/test/templates/unicode.html | 2 + lib/mako-0.7.2/test/templates/unicode_arguments.html | 10 + lib/mako-0.7.2/test/templates/unicode_arguments_py3k.html | 10 + lib/mako-0.7.2/test/templates/unicode_code.html | 7 + lib/mako-0.7.2/test/templates/unicode_code_py3k.html | 7 + lib/mako-0.7.2/test/templates/unicode_expr.html | 2 + lib/mako-0.7.2/test/templates/unicode_expr_py3k.html | 2 + lib/mako-0.7.2/test/templates/unicode_runtime_error.html | 2 + lib/mako-0.7.2/test/templates/unicode_syntax_error.html | 2 + lib/mako-0.7.2/test/test_ast.py | 322 ++ lib/mako-0.7.2/test/test_babelplugin.py | 44 + lib/mako-0.7.2/test/test_block.py | 569 ++++ lib/mako-0.7.2/test/test_cache.py | 557 ++++ lib/mako-0.7.2/test/test_call.py | 515 ++++ lib/mako-0.7.2/test/test_decorators.py | 110 + lib/mako-0.7.2/test/test_def.py | 678 +++++ lib/mako-0.7.2/test/test_exceptions.py | 296 ++ lib/mako-0.7.2/test/test_filters.py | 322 ++ lib/mako-0.7.2/test/test_inheritance.py | 350 ++ lib/mako-0.7.2/test/test_lexer.py | 871 +++++++ lib/mako-0.7.2/test/test_lookup.py | 104 + lib/mako-0.7.2/test/test_loop.py | 295 ++ lib/mako-0.7.2/test/test_lru.py | 111 + lib/mako-0.7.2/test/test_namespace.py | 792 ++++++ lib/mako-0.7.2/test/test_pygen.py | 252 ++ lib/mako-0.7.2/test/test_template.py | 1241 ++++++++++ lib/mako-0.7.2/test/test_tgplugin.py | 42 + lib/mako-0.7.2/test/test_util.py | 41 + lib/mako-0.7.2/test/util.py | 7 + make_perf3.sh | 2 +- perf.py | 17 +- performance/bm_mako_v2.py | 154 + 297 files changed, 39306 insertions(+), 4 deletions(-) diff --git a/lib/mako/.hgignore b/lib/mako-0.3.6/.hgignore rename from lib/mako/.hgignore rename to lib/mako-0.3.6/.hgignore diff --git a/lib/mako/CHANGES b/lib/mako-0.3.6/CHANGES rename from lib/mako/CHANGES rename to lib/mako-0.3.6/CHANGES diff --git a/lib/mako/LICENSE b/lib/mako-0.3.6/LICENSE rename from lib/mako/LICENSE rename to lib/mako-0.3.6/LICENSE diff --git a/lib/mako/MANIFEST.in b/lib/mako-0.3.6/MANIFEST.in rename from lib/mako/MANIFEST.in rename to lib/mako-0.3.6/MANIFEST.in diff --git a/lib/mako/README b/lib/mako-0.3.6/README rename from lib/mako/README rename to lib/mako-0.3.6/README diff --git a/lib/mako/README.py3k b/lib/mako-0.3.6/README.py3k rename from lib/mako/README.py3k rename to lib/mako-0.3.6/README.py3k diff --git a/lib/mako/distribute_setup.py b/lib/mako-0.3.6/distribute_setup.py rename from lib/mako/distribute_setup.py rename to lib/mako-0.3.6/distribute_setup.py diff --git a/lib/mako/doc/build/Makefile b/lib/mako-0.3.6/doc/build/Makefile rename from lib/mako/doc/build/Makefile rename to lib/mako-0.3.6/doc/build/Makefile diff --git a/lib/mako/doc/build/builder/builders.py b/lib/mako-0.3.6/doc/build/builder/builders.py rename from lib/mako/doc/build/builder/builders.py rename to lib/mako-0.3.6/doc/build/builder/builders.py diff --git a/lib/mako/doc/build/builder/util.py b/lib/mako-0.3.6/doc/build/builder/util.py rename from lib/mako/doc/build/builder/util.py rename to lib/mako-0.3.6/doc/build/builder/util.py diff --git a/lib/mako/doc/build/caching.rst b/lib/mako-0.3.6/doc/build/caching.rst rename from lib/mako/doc/build/caching.rst rename to lib/mako-0.3.6/doc/build/caching.rst diff --git a/lib/mako/doc/build/conf.py b/lib/mako-0.3.6/doc/build/conf.py rename from lib/mako/doc/build/conf.py rename to lib/mako-0.3.6/doc/build/conf.py diff --git a/lib/mako/doc/build/defs.rst b/lib/mako-0.3.6/doc/build/defs.rst rename from lib/mako/doc/build/defs.rst rename to lib/mako-0.3.6/doc/build/defs.rst diff --git a/lib/mako/doc/build/filtering.rst b/lib/mako-0.3.6/doc/build/filtering.rst rename from lib/mako/doc/build/filtering.rst rename to lib/mako-0.3.6/doc/build/filtering.rst diff --git a/lib/mako/doc/build/index.rst b/lib/mako-0.3.6/doc/build/index.rst rename from lib/mako/doc/build/index.rst rename to lib/mako-0.3.6/doc/build/index.rst diff --git a/lib/mako/doc/build/inheritance.rst b/lib/mako-0.3.6/doc/build/inheritance.rst rename from lib/mako/doc/build/inheritance.rst rename to lib/mako-0.3.6/doc/build/inheritance.rst diff --git a/lib/mako/doc/build/namespaces.rst b/lib/mako-0.3.6/doc/build/namespaces.rst rename from lib/mako/doc/build/namespaces.rst rename to lib/mako-0.3.6/doc/build/namespaces.rst diff --git a/lib/mako/doc/build/runtime.rst b/lib/mako-0.3.6/doc/build/runtime.rst rename from lib/mako/doc/build/runtime.rst rename to lib/mako-0.3.6/doc/build/runtime.rst diff --git a/lib/mako/doc/build/static/docs.css b/lib/mako-0.3.6/doc/build/static/docs.css rename from lib/mako/doc/build/static/docs.css rename to lib/mako-0.3.6/doc/build/static/docs.css diff --git a/lib/mako/doc/build/syntax.rst b/lib/mako-0.3.6/doc/build/syntax.rst rename from lib/mako/doc/build/syntax.rst rename to lib/mako-0.3.6/doc/build/syntax.rst diff --git a/lib/mako/doc/build/templates/genindex.mako b/lib/mako-0.3.6/doc/build/templates/genindex.mako rename from lib/mako/doc/build/templates/genindex.mako rename to lib/mako-0.3.6/doc/build/templates/genindex.mako diff --git a/lib/mako/doc/build/templates/layout.mako b/lib/mako-0.3.6/doc/build/templates/layout.mako rename from lib/mako/doc/build/templates/layout.mako rename to lib/mako-0.3.6/doc/build/templates/layout.mako diff --git a/lib/mako/doc/build/templates/page.mako b/lib/mako-0.3.6/doc/build/templates/page.mako rename from lib/mako/doc/build/templates/page.mako rename to lib/mako-0.3.6/doc/build/templates/page.mako diff --git a/lib/mako/doc/build/templates/search.mako b/lib/mako-0.3.6/doc/build/templates/search.mako rename from lib/mako/doc/build/templates/search.mako rename to lib/mako-0.3.6/doc/build/templates/search.mako diff --git a/lib/mako/doc/build/templates/site_base.mako b/lib/mako-0.3.6/doc/build/templates/site_base.mako rename from lib/mako/doc/build/templates/site_base.mako rename to lib/mako-0.3.6/doc/build/templates/site_base.mako diff --git a/lib/mako/doc/build/templates/static_base.mako b/lib/mako-0.3.6/doc/build/templates/static_base.mako rename from lib/mako/doc/build/templates/static_base.mako rename to lib/mako-0.3.6/doc/build/templates/static_base.mako diff --git a/lib/mako/doc/build/unicode.rst b/lib/mako-0.3.6/doc/build/unicode.rst rename from lib/mako/doc/build/unicode.rst rename to lib/mako-0.3.6/doc/build/unicode.rst diff --git a/lib/mako/doc/build/usage.rst b/lib/mako-0.3.6/doc/build/usage.rst rename from lib/mako/doc/build/usage.rst rename to lib/mako-0.3.6/doc/build/usage.rst diff --git a/lib/mako/examples/bench/basic.py b/lib/mako-0.3.6/examples/bench/basic.py rename from lib/mako/examples/bench/basic.py rename to lib/mako-0.3.6/examples/bench/basic.py diff --git a/lib/mako/examples/bench/basic.py.orig b/lib/mako-0.3.6/examples/bench/basic.py.orig rename from lib/mako/examples/bench/basic.py.orig rename to lib/mako-0.3.6/examples/bench/basic.py.orig diff --git a/lib/mako/examples/bench/cheetah/footer.tmpl b/lib/mako-0.3.6/examples/bench/cheetah/footer.tmpl rename from lib/mako/examples/bench/cheetah/footer.tmpl rename to lib/mako-0.3.6/examples/bench/cheetah/footer.tmpl diff --git a/lib/mako/examples/bench/cheetah/header.tmpl b/lib/mako-0.3.6/examples/bench/cheetah/header.tmpl rename from lib/mako/examples/bench/cheetah/header.tmpl rename to lib/mako-0.3.6/examples/bench/cheetah/header.tmpl diff --git a/lib/mako/examples/bench/cheetah/template.tmpl b/lib/mako-0.3.6/examples/bench/cheetah/template.tmpl rename from lib/mako/examples/bench/cheetah/template.tmpl rename to lib/mako-0.3.6/examples/bench/cheetah/template.tmpl diff --git a/lib/mako/examples/bench/django/templates/base.html b/lib/mako-0.3.6/examples/bench/django/templates/base.html rename from lib/mako/examples/bench/django/templates/base.html rename to lib/mako-0.3.6/examples/bench/django/templates/base.html diff --git a/lib/mako/examples/bench/django/templates/template.html b/lib/mako-0.3.6/examples/bench/django/templates/template.html rename from lib/mako/examples/bench/django/templates/template.html rename to lib/mako-0.3.6/examples/bench/django/templates/template.html diff --git a/lib/mako/examples/bench/django/templatetags/bench.py b/lib/mako-0.3.6/examples/bench/django/templatetags/bench.py rename from lib/mako/examples/bench/django/templatetags/bench.py rename to lib/mako-0.3.6/examples/bench/django/templatetags/bench.py diff --git a/lib/mako/examples/bench/genshi/base.html b/lib/mako-0.3.6/examples/bench/genshi/base.html rename from lib/mako/examples/bench/genshi/base.html rename to lib/mako-0.3.6/examples/bench/genshi/base.html diff --git a/lib/mako/examples/bench/genshi/template.html b/lib/mako-0.3.6/examples/bench/genshi/template.html rename from lib/mako/examples/bench/genshi/template.html rename to lib/mako-0.3.6/examples/bench/genshi/template.html diff --git a/lib/mako/examples/bench/kid/base.kid b/lib/mako-0.3.6/examples/bench/kid/base.kid rename from lib/mako/examples/bench/kid/base.kid rename to lib/mako-0.3.6/examples/bench/kid/base.kid diff --git a/lib/mako/examples/bench/kid/template.kid b/lib/mako-0.3.6/examples/bench/kid/template.kid rename from lib/mako/examples/bench/kid/template.kid rename to lib/mako-0.3.6/examples/bench/kid/template.kid diff --git a/lib/mako/examples/bench/mako/footer.html b/lib/mako-0.3.6/examples/bench/mako/footer.html rename from lib/mako/examples/bench/mako/footer.html rename to lib/mako-0.3.6/examples/bench/mako/footer.html diff --git a/lib/mako/examples/bench/mako/header.html b/lib/mako-0.3.6/examples/bench/mako/header.html rename from lib/mako/examples/bench/mako/header.html rename to lib/mako-0.3.6/examples/bench/mako/header.html diff --git a/lib/mako/examples/bench/mako/template.html b/lib/mako-0.3.6/examples/bench/mako/template.html rename from lib/mako/examples/bench/mako/template.html rename to lib/mako-0.3.6/examples/bench/mako/template.html diff --git a/lib/mako/examples/bench/mako_inheritance/base.html b/lib/mako-0.3.6/examples/bench/mako_inheritance/base.html rename from lib/mako/examples/bench/mako_inheritance/base.html rename to lib/mako-0.3.6/examples/bench/mako_inheritance/base.html diff --git a/lib/mako/examples/bench/mako_inheritance/template.html b/lib/mako-0.3.6/examples/bench/mako_inheritance/template.html rename from lib/mako/examples/bench/mako_inheritance/template.html rename to lib/mako-0.3.6/examples/bench/mako_inheritance/template.html diff --git a/lib/mako/examples/bench/myghty/base.myt b/lib/mako-0.3.6/examples/bench/myghty/base.myt rename from lib/mako/examples/bench/myghty/base.myt rename to lib/mako-0.3.6/examples/bench/myghty/base.myt diff --git a/lib/mako/examples/bench/myghty/template.myt b/lib/mako-0.3.6/examples/bench/myghty/template.myt rename from lib/mako/examples/bench/myghty/template.myt rename to lib/mako-0.3.6/examples/bench/myghty/template.myt diff --git a/lib/mako/examples/wsgi/htdocs/index.html b/lib/mako-0.3.6/examples/wsgi/htdocs/index.html rename from lib/mako/examples/wsgi/htdocs/index.html rename to lib/mako-0.3.6/examples/wsgi/htdocs/index.html diff --git a/lib/mako/examples/wsgi/run_wsgi.py b/lib/mako-0.3.6/examples/wsgi/run_wsgi.py rename from lib/mako/examples/wsgi/run_wsgi.py rename to lib/mako-0.3.6/examples/wsgi/run_wsgi.py diff --git a/lib/mako/examples/wsgi/templates/root.html b/lib/mako-0.3.6/examples/wsgi/templates/root.html rename from lib/mako/examples/wsgi/templates/root.html rename to lib/mako-0.3.6/examples/wsgi/templates/root.html diff --git a/lib/mako/mako/__init__.py b/lib/mako-0.3.6/mako/__init__.py rename from lib/mako/mako/__init__.py rename to lib/mako-0.3.6/mako/__init__.py diff --git a/lib/mako/mako/_ast_util.py b/lib/mako-0.3.6/mako/_ast_util.py rename from lib/mako/mako/_ast_util.py rename to lib/mako-0.3.6/mako/_ast_util.py diff --git a/lib/mako/mako/ast.py b/lib/mako-0.3.6/mako/ast.py rename from lib/mako/mako/ast.py rename to lib/mako-0.3.6/mako/ast.py diff --git a/lib/mako/mako/cache.py b/lib/mako-0.3.6/mako/cache.py rename from lib/mako/mako/cache.py rename to lib/mako-0.3.6/mako/cache.py diff --git a/lib/mako/mako/codegen.py b/lib/mako-0.3.6/mako/codegen.py rename from lib/mako/mako/codegen.py rename to lib/mako-0.3.6/mako/codegen.py diff --git a/lib/mako/mako/exceptions.py b/lib/mako-0.3.6/mako/exceptions.py rename from lib/mako/mako/exceptions.py rename to lib/mako-0.3.6/mako/exceptions.py diff --git a/lib/mako/mako/ext/autohandler.py b/lib/mako-0.3.6/mako/ext/autohandler.py rename from lib/mako/mako/ext/autohandler.py rename to lib/mako-0.3.6/mako/ext/autohandler.py diff --git a/lib/mako/mako/ext/babelplugin.py b/lib/mako-0.3.6/mako/ext/babelplugin.py rename from lib/mako/mako/ext/babelplugin.py rename to lib/mako-0.3.6/mako/ext/babelplugin.py diff --git a/lib/mako/mako/ext/preprocessors.py b/lib/mako-0.3.6/mako/ext/preprocessors.py rename from lib/mako/mako/ext/preprocessors.py rename to lib/mako-0.3.6/mako/ext/preprocessors.py diff --git a/lib/mako/mako/ext/pygmentplugin.py b/lib/mako-0.3.6/mako/ext/pygmentplugin.py rename from lib/mako/mako/ext/pygmentplugin.py rename to lib/mako-0.3.6/mako/ext/pygmentplugin.py diff --git a/lib/mako/mako/ext/turbogears.py b/lib/mako-0.3.6/mako/ext/turbogears.py rename from lib/mako/mako/ext/turbogears.py rename to lib/mako-0.3.6/mako/ext/turbogears.py diff --git a/lib/mako/mako/filters.py b/lib/mako-0.3.6/mako/filters.py rename from lib/mako/mako/filters.py rename to lib/mako-0.3.6/mako/filters.py diff --git a/lib/mako/mako/lexer.py b/lib/mako-0.3.6/mako/lexer.py rename from lib/mako/mako/lexer.py rename to lib/mako-0.3.6/mako/lexer.py diff --git a/lib/mako/mako/lookup.py b/lib/mako-0.3.6/mako/lookup.py rename from lib/mako/mako/lookup.py rename to lib/mako-0.3.6/mako/lookup.py diff --git a/lib/mako/mako/parsetree.py b/lib/mako-0.3.6/mako/parsetree.py rename from lib/mako/mako/parsetree.py rename to lib/mako-0.3.6/mako/parsetree.py diff --git a/lib/mako/mako/pygen.py b/lib/mako-0.3.6/mako/pygen.py rename from lib/mako/mako/pygen.py rename to lib/mako-0.3.6/mako/pygen.py diff --git a/lib/mako/mako/pyparser.py b/lib/mako-0.3.6/mako/pyparser.py rename from lib/mako/mako/pyparser.py rename to lib/mako-0.3.6/mako/pyparser.py diff --git a/lib/mako/mako/runtime.py b/lib/mako-0.3.6/mako/runtime.py rename from lib/mako/mako/runtime.py rename to lib/mako-0.3.6/mako/runtime.py diff --git a/lib/mako/mako/template.py b/lib/mako-0.3.6/mako/template.py rename from lib/mako/mako/template.py rename to lib/mako-0.3.6/mako/template.py diff --git a/lib/mako/mako/util.py b/lib/mako-0.3.6/mako/util.py rename from lib/mako/mako/util.py rename to lib/mako-0.3.6/mako/util.py diff --git a/lib/mako/scripts/mako-render b/lib/mako-0.3.6/scripts/mako-render rename from lib/mako/scripts/mako-render rename to lib/mako-0.3.6/scripts/mako-render diff --git a/lib/mako/setup.cfg b/lib/mako-0.3.6/setup.cfg rename from lib/mako/setup.cfg rename to lib/mako-0.3.6/setup.cfg diff --git a/lib/mako/setup.py b/lib/mako-0.3.6/setup.py rename from lib/mako/setup.py rename to lib/mako-0.3.6/setup.py diff --git a/lib/mako/test/__init__.py b/lib/mako-0.3.6/test/__init__.py rename from lib/mako/test/__init__.py rename to lib/mako-0.3.6/test/__init__.py diff --git a/lib/mako/test/foo/test_ns.py b/lib/mako-0.3.6/test/foo/test_ns.py rename from lib/mako/test/foo/test_ns.py rename to lib/mako-0.3.6/test/foo/test_ns.py diff --git a/lib/mako/test/sample_module_namespace.py b/lib/mako-0.3.6/test/sample_module_namespace.py rename from lib/mako/test/sample_module_namespace.py rename to lib/mako-0.3.6/test/sample_module_namespace.py diff --git a/lib/mako/test/templates/badbom.html b/lib/mako-0.3.6/test/templates/badbom.html rename from lib/mako/test/templates/badbom.html rename to lib/mako-0.3.6/test/templates/badbom.html diff --git a/lib/mako/test/templates/bom.html b/lib/mako-0.3.6/test/templates/bom.html rename from lib/mako/test/templates/bom.html rename to lib/mako-0.3.6/test/templates/bom.html diff --git a/lib/mako/test/templates/bommagic.html b/lib/mako-0.3.6/test/templates/bommagic.html rename from lib/mako/test/templates/bommagic.html rename to lib/mako-0.3.6/test/templates/bommagic.html diff --git a/lib/mako/test/templates/chs_unicode.html b/lib/mako-0.3.6/test/templates/chs_unicode.html rename from lib/mako/test/templates/chs_unicode.html rename to lib/mako-0.3.6/test/templates/chs_unicode.html diff --git a/lib/mako/test/templates/chs_unicode_py3k.html b/lib/mako-0.3.6/test/templates/chs_unicode_py3k.html rename from lib/mako/test/templates/chs_unicode_py3k.html rename to lib/mako-0.3.6/test/templates/chs_unicode_py3k.html diff --git a/lib/mako/test/templates/chs_utf8.html b/lib/mako-0.3.6/test/templates/chs_utf8.html rename from lib/mako/test/templates/chs_utf8.html rename to lib/mako-0.3.6/test/templates/chs_utf8.html diff --git a/lib/mako/test/templates/crlf.html b/lib/mako-0.3.6/test/templates/crlf.html rename from lib/mako/test/templates/crlf.html rename to lib/mako-0.3.6/test/templates/crlf.html diff --git a/lib/mako/test/templates/foo/modtest.html.py b/lib/mako-0.3.6/test/templates/foo/modtest.html.py rename from lib/mako/test/templates/foo/modtest.html.py rename to lib/mako-0.3.6/test/templates/foo/modtest.html.py diff --git a/lib/mako/test/templates/gettext.mako b/lib/mako-0.3.6/test/templates/gettext.mako rename from lib/mako/test/templates/gettext.mako rename to lib/mako-0.3.6/test/templates/gettext.mako diff --git a/lib/mako/test/templates/index.html b/lib/mako-0.3.6/test/templates/index.html rename from lib/mako/test/templates/index.html rename to lib/mako-0.3.6/test/templates/index.html diff --git a/lib/mako/test/templates/internationalization.html b/lib/mako-0.3.6/test/templates/internationalization.html rename from lib/mako/test/templates/internationalization.html rename to lib/mako-0.3.6/test/templates/internationalization.html diff --git a/lib/mako/test/templates/modtest.html b/lib/mako-0.3.6/test/templates/modtest.html rename from lib/mako/test/templates/modtest.html rename to lib/mako-0.3.6/test/templates/modtest.html diff --git a/lib/mako/test/templates/read_unicode.html b/lib/mako-0.3.6/test/templates/read_unicode.html rename from lib/mako/test/templates/read_unicode.html rename to lib/mako-0.3.6/test/templates/read_unicode.html diff --git a/lib/mako/test/templates/read_unicode_py3k.html b/lib/mako-0.3.6/test/templates/read_unicode_py3k.html rename from lib/mako/test/templates/read_unicode_py3k.html rename to lib/mako-0.3.6/test/templates/read_unicode_py3k.html diff --git a/lib/mako/test/templates/runtimeerr.html b/lib/mako-0.3.6/test/templates/runtimeerr.html rename from lib/mako/test/templates/runtimeerr.html rename to lib/mako-0.3.6/test/templates/runtimeerr.html diff --git a/lib/mako/test/templates/runtimeerr_py3k.html b/lib/mako-0.3.6/test/templates/runtimeerr_py3k.html rename from lib/mako/test/templates/runtimeerr_py3k.html rename to lib/mako-0.3.6/test/templates/runtimeerr_py3k.html diff --git a/lib/mako/test/templates/subdir/foo/modtest.html.py b/lib/mako-0.3.6/test/templates/subdir/foo/modtest.html.py rename from lib/mako/test/templates/subdir/foo/modtest.html.py rename to lib/mako-0.3.6/test/templates/subdir/foo/modtest.html.py diff --git a/lib/mako/test/templates/subdir/incl.html b/lib/mako-0.3.6/test/templates/subdir/incl.html rename from lib/mako/test/templates/subdir/incl.html rename to lib/mako-0.3.6/test/templates/subdir/incl.html diff --git a/lib/mako/test/templates/subdir/index.html b/lib/mako-0.3.6/test/templates/subdir/index.html rename from lib/mako/test/templates/subdir/index.html rename to lib/mako-0.3.6/test/templates/subdir/index.html diff --git a/lib/mako/test/templates/subdir/modtest.html b/lib/mako-0.3.6/test/templates/subdir/modtest.html rename from lib/mako/test/templates/subdir/modtest.html rename to lib/mako-0.3.6/test/templates/subdir/modtest.html diff --git a/lib/mako/test/templates/unicode.html b/lib/mako-0.3.6/test/templates/unicode.html rename from lib/mako/test/templates/unicode.html rename to lib/mako-0.3.6/test/templates/unicode.html diff --git a/lib/mako/test/templates/unicode_arguments.html b/lib/mako-0.3.6/test/templates/unicode_arguments.html rename from lib/mako/test/templates/unicode_arguments.html rename to lib/mako-0.3.6/test/templates/unicode_arguments.html diff --git a/lib/mako/test/templates/unicode_arguments_py3k.html b/lib/mako-0.3.6/test/templates/unicode_arguments_py3k.html rename from lib/mako/test/templates/unicode_arguments_py3k.html rename to lib/mako-0.3.6/test/templates/unicode_arguments_py3k.html diff --git a/lib/mako/test/templates/unicode_code.html b/lib/mako-0.3.6/test/templates/unicode_code.html rename from lib/mako/test/templates/unicode_code.html rename to lib/mako-0.3.6/test/templates/unicode_code.html diff --git a/lib/mako/test/templates/unicode_code_py3k.html b/lib/mako-0.3.6/test/templates/unicode_code_py3k.html rename from lib/mako/test/templates/unicode_code_py3k.html rename to lib/mako-0.3.6/test/templates/unicode_code_py3k.html diff --git a/lib/mako/test/templates/unicode_expr.html b/lib/mako-0.3.6/test/templates/unicode_expr.html rename from lib/mako/test/templates/unicode_expr.html rename to lib/mako-0.3.6/test/templates/unicode_expr.html diff --git a/lib/mako/test/templates/unicode_expr_py3k.html b/lib/mako-0.3.6/test/templates/unicode_expr_py3k.html rename from lib/mako/test/templates/unicode_expr_py3k.html rename to lib/mako-0.3.6/test/templates/unicode_expr_py3k.html diff --git a/lib/mako/test/templates/unicode_runtime_error.html b/lib/mako-0.3.6/test/templates/unicode_runtime_error.html rename from lib/mako/test/templates/unicode_runtime_error.html rename to lib/mako-0.3.6/test/templates/unicode_runtime_error.html diff --git a/lib/mako/test/templates/unicode_syntax_error.html b/lib/mako-0.3.6/test/templates/unicode_syntax_error.html rename from lib/mako/test/templates/unicode_syntax_error.html rename to lib/mako-0.3.6/test/templates/unicode_syntax_error.html diff --git a/lib/mako/test/test_ast.py b/lib/mako-0.3.6/test/test_ast.py rename from lib/mako/test/test_ast.py rename to lib/mako-0.3.6/test/test_ast.py diff --git a/lib/mako/test/test_babelplugin.py b/lib/mako-0.3.6/test/test_babelplugin.py rename from lib/mako/test/test_babelplugin.py rename to lib/mako-0.3.6/test/test_babelplugin.py diff --git a/lib/mako/test/test_cache.py b/lib/mako-0.3.6/test/test_cache.py rename from lib/mako/test/test_cache.py rename to lib/mako-0.3.6/test/test_cache.py diff --git a/lib/mako/test/test_call.py b/lib/mako-0.3.6/test/test_call.py rename from lib/mako/test/test_call.py rename to lib/mako-0.3.6/test/test_call.py diff --git a/lib/mako/test/test_decorators.py b/lib/mako-0.3.6/test/test_decorators.py rename from lib/mako/test/test_decorators.py rename to lib/mako-0.3.6/test/test_decorators.py diff --git a/lib/mako/test/test_def.py b/lib/mako-0.3.6/test/test_def.py rename from lib/mako/test/test_def.py rename to lib/mako-0.3.6/test/test_def.py diff --git a/lib/mako/test/test_exceptions.py b/lib/mako-0.3.6/test/test_exceptions.py rename from lib/mako/test/test_exceptions.py rename to lib/mako-0.3.6/test/test_exceptions.py diff --git a/lib/mako/test/test_filters.py b/lib/mako-0.3.6/test/test_filters.py rename from lib/mako/test/test_filters.py rename to lib/mako-0.3.6/test/test_filters.py diff --git a/lib/mako/test/test_inheritance.py b/lib/mako-0.3.6/test/test_inheritance.py rename from lib/mako/test/test_inheritance.py rename to lib/mako-0.3.6/test/test_inheritance.py diff --git a/lib/mako/test/test_lexer.py b/lib/mako-0.3.6/test/test_lexer.py rename from lib/mako/test/test_lexer.py rename to lib/mako-0.3.6/test/test_lexer.py diff --git a/lib/mako/test/test_lookup.py b/lib/mako-0.3.6/test/test_lookup.py rename from lib/mako/test/test_lookup.py rename to lib/mako-0.3.6/test/test_lookup.py diff --git a/lib/mako/test/test_lru.py b/lib/mako-0.3.6/test/test_lru.py rename from lib/mako/test/test_lru.py rename to lib/mako-0.3.6/test/test_lru.py diff --git a/lib/mako/test/test_namespace.py b/lib/mako-0.3.6/test/test_namespace.py rename from lib/mako/test/test_namespace.py rename to lib/mako-0.3.6/test/test_namespace.py diff --git a/lib/mako/test/test_pygen.py b/lib/mako-0.3.6/test/test_pygen.py rename from lib/mako/test/test_pygen.py rename to lib/mako-0.3.6/test/test_pygen.py diff --git a/lib/mako/test/test_template.py b/lib/mako-0.3.6/test/test_template.py rename from lib/mako/test/test_template.py rename to lib/mako-0.3.6/test/test_template.py diff --git a/lib/mako/test/test_tgplugin.py b/lib/mako-0.3.6/test/test_tgplugin.py rename from lib/mako/test/test_tgplugin.py rename to lib/mako-0.3.6/test/test_tgplugin.py diff --git a/lib/mako/test/util.py b/lib/mako-0.3.6/test/util.py rename from lib/mako/test/util.py rename to lib/mako-0.3.6/test/util.py diff --git a/lib/mako-0.7.2/CHANGES b/lib/mako-0.7.2/CHANGES new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/CHANGES @@ -0,0 +1,825 @@ +0.7.2 +- [bug] Fixed regression in 0.7.1 where AST + parsing for Py2.4 was broken. + [ticket:193] + +0.7.1 +- [feature] Control lines with no bodies will + now succeed, as "pass" is added for these + when no statements are otherwise present. + Courtesy Ben Trofatter [ticket:146] + +- [bug] Fixed some long-broken scoping behavior + involving variables declared in defs and such, + which only became apparent when + the strict_undefined flag was turned on. + [ticket:192] + +- [bug] Can now use strict_undefined at the + same time args passed to def() are used + by other elements of the <%def> tag. + [ticket:191] + +0.7.0 +- [feature] Added new "loop" variable to templates, + is provided within a % for block to provide + info about the loop such as index, first/last, + odd/even, etc. A migration path is also provided + for legacy templates via the "enable_loop" argument + available on Template, TemplateLookup, and <%page>. + Thanks to Ben Trofatter for all + the work on this [ticket:125] + +- [feature] Added a real check for "reserved" + names, that is names which are never pulled + from the context and cannot be passed to + the template.render() method. Current names + are "context", "loop", "UNDEFINED". + +- [feature] The html_error_template() will now + apply Pygments highlighting to the source + code displayed in the traceback, if Pygments + if available. Courtesy Ben Trofatter + [ticket:95] + +- [feature] Added support for context managers, + i.e. "% with x as e:/ % endwith" support. + Courtesy Ben Trofatter [ticket:147] + +- [feature] Added class-level flag to CacheImpl + "pass_context"; when True, the keyword argument + 'context' will be passed to get_or_create() + containing the Mako Context object. + [ticket:185] + +- [bug] Fixed some Py3K resource warnings due + to filehandles being implicitly closed. + [ticket:182] + +- [bug] Fixed endless recursion bug when + nesting multiple def-calls with content. + Thanks to Jeff Dairiki. [ticket:186] + +- [feature] Added Jinja2 to the example + benchmark suite, courtesy Vincent F?rotin + +0.6.2 +- [bug] The ${{"foo":"bar"}} parsing issue is fixed!! + The legendary Eevee has slain the dragon! + [ticket:20]. Also fixes quoting issue + at [ticket:86]. + +0.6.1 +- [bug] Added special compatibility for the 0.5.0 + Cache() constructor, which was preventing file + version checks and not allowing Mako 0.6 to + recompile the module files. + +0.6.0 + +- [feature] Template caching has been converted into a plugin + system, whereby the usage of Beaker is just the + default plugin. Template and TemplateLookup + now accept a string "cache_impl" parameter which + refers to the name of a cache plugin, defaulting + to the name 'beaker'. New plugins can be + registered as pkg_resources entrypoints under + the group "mako.cache", or registered directly + using mako.cache.register_plugin(). The + core plugin is the mako.cache.CacheImpl + class. + +- [feature] Added support for Beaker cache regions + in templates. Usage of regions should be considered + as superseding the very obsolete idea of passing in + backend options, timeouts, etc. within templates. + +- [feature] The 'put' method on Cache is now + 'set'. 'put' is there for backwards compatibility. + +- [feature] The <%def>, <%block> and <%page> tags now accept + any argument named "cache_*", and the key + minus the "cache_" prefix will be passed as keyword + arguments to the CacheImpl methods. + +- [feature] Template and TemplateLookup now accept an argument + cache_args, which refers to a dictionary containing + cache parameters. The cache_dir, cache_url, cache_type, + cache_timeout arguments are deprecated (will probably + never be removed, however) and can be passed + now as cache_args={'url':, 'type':'memcached', + 'timeout':50, 'dir':'/path/to/some/directory'} + +- [feature/bug] Can now refer to context variables + within extra arguments to <%block>, <%def>, i.e. + <%block name="foo" cache_key="${somekey}">. + Filters can also be used in this way, i.e. + <%def name="foo()" filter="myfilter"> + then template.render(myfilter=some_callable) + [ticket:180] + +- [feature] Added "--var name=value" option to the mako-render + script, allows passing of kw to the template from + the command line. [ticket:178] + +- [feature] Added module_writer argument to Template, + TemplateLookup, allows a callable to be passed which + takes over the writing of the template's module source + file, so that special environment-specific steps + can be taken. [ticket:181] + +- [bug] The exception message in the html_error_template + is now escaped with the HTML filter. [ticket:142] + +- [bug] Added "white-space:pre" style to html_error_template() + for code blocks so that indentation is preserved + [ticket:173] + +- [bug] The "benchmark" example is now Python 3 compatible + (even though several of those old template libs aren't + available on Py3K, so YMMV) [ticket:175] + +0.5 +- A Template is explicitly disallowed + from having a url that normalizes to relative outside + of the root. That is, if the Lookup is based + at /home/mytemplates, an include that would place + the ultimate template at + /home/mytemplates/../some_other_directory, + i.e. outside of /home/mytemplates, + is disallowed. This usage was never intended + despite the lack of an explicit check. + The main issue this causes + is that module files can be written outside + of the module root (or raise an error, if file perms aren't + set up), and can also lead to the same template being + cached in the lookup under multiple, relative roots. + TemplateLookup instead has always supported multiple + file roots for this purpose. + [ticket:174] + +0.4.2 +- Fixed bug regarding <%call>/def calls w/ content + whereby the identity of the "caller" callable + inside the <%def> would be corrupted by the + presence of another <%call> in the same block. + [ticket:170] + +- Fixed the babel plugin to accommodate <%block> + [ticket:169] + +0.4.1 +- New tag: <%block>. A variant on <%def> that + evaluates its contents in-place. + Can be named or anonymous, + the named version is intended for inheritance + layouts where any given section can be + surrounded by the <%block> tag in order for + it to become overrideable by inheriting + templates, without the need to specify a + top-level <%def> plus explicit call. + Modified scoping and argument rules as well as a + more strictly enforced usage scheme make it ideal + for this purpose without at all replacing most + other things that defs are still good for. + Lots of new docs. [ticket:164] + +- a slight adjustment to the "highlight" logic + for generating template bound stacktraces. + Will stick to known template source lines + without any extra guessing. [ticket:165] + +0.4.0 +- A 20% speedup for a basic two-page + inheritance setup rendering + a table of escaped data + (see http://techspot.zzzeek.org/2010/11/19/quick-mako-vs.-jinja-speed-test/). + A few configurational changes which + affect those in the I-don't-do-unicode + camp should be noted below. + +- The FastEncodingBuffer is now used + by default instead of cStringIO or StringIO, + regardless of whether output_encoding + is set to None or not. FEB is faster than + both. Only StringIO allows bytestrings + of unknown encoding to pass right + through, however - while it is of course + not recommended to send bytestrings of unknown + encoding to the output stream, this + mode of usage can be re-enabled by + setting the flag bytestring_passthrough + to True. + +- disable_unicode mode requires that + output_encoding be set to None - it also + forces the bytestring_passthrough flag + to True. + +- the <%namespace> tag raises an error + if the 'template' and 'module' attributes + are specified at the same time in + one tag. A different class is used + for each case which allows a reduction in + runtime conditional logic and function + call overhead. [ticket:156] + +- the keys() in the Context, as well as + it's internal _data dictionary, now + include just what was specified to + render() as well as Mako builtins + 'caller', 'capture'. The contents + of __builtin__ are no longer copied. + Thanks to Daniel Lopez for pointing + this out. [ticket:159] + +0.3.6 +- Documentation is on Sphinx. + [ticket:126] + +- Beaker is now part of "extras" in + setup.py instead of "install_requires". + This to produce a lighter weight install + for those who don't use the caching + as well as to conform to Pyramid + deployment practices. [ticket:154] + +- The Beaker import (or attempt thereof) + is delayed until actually needed; + this to remove the performance penalty + from startup, particularly for + "single execution" environments + such as shell scripts. [ticket:153] + +- Patch to lexer to not generate an empty + '' write in the case of backslash-ended + lines. [ticket:155] + +- Fixed missing **extra collection in + setup.py which prevented setup.py + from running 2to3 on install. + [ticket:148] + +- New flag on Template, TemplateLookup - + strict_undefined=True, will cause + variables not found in the context to + raise a NameError immediately, instead of + defaulting to the UNDEFINED value. + +- The range of Python identifiers that + are considered "undefined", meaning they + are pulled from the context, has been + trimmed back to not include variables + declared inside of expressions (i.e. from + list comprehensions), as well as + in the argument list of lambdas. This + to better support the strict_undefined + feature. The change should be + fully backwards-compatible but involved + a little bit of tinkering in the AST code, + which hadn't really been touched for + a couple of years, just FYI. + +0.3.5 +- The <%namespace> tag allows expressions + for the `file` argument, i.e. with ${}. + The `context` variable, if needed, + must be referenced explicitly. + [ticket:141] + +- ${} expressions embedded in tags, + such as <%foo:bar x="${...}">, now + allow multiline Python expressions. + +- Fixed previously non-covered regular + expression, such that using a ${} expression + inside of a tag element that doesn't allow + them raises a CompileException instead of + silently failing. + +- Added a try/except around "import markupsafe". + This to support GAE which can't run markupsafe. + [ticket:151] No idea whatsoever if the + install_requires in setup.py also breaks GAE, + couldn't get an answer on this. + +0.3.4 +- Now using MarkupSafe for HTML escaping, + i.e. in place of cgi.escape(). Faster + C-based implementation and also escapes + single quotes for additional security. + Supports the __html__ attribute for + the given expression as well. + + When using "disable_unicode" mode, + a pure Python HTML escaper function + is used which also quotes single quotes. + + Note that Pylons by default doesn't + use Mako's filter - check your + environment.py file. + +- Fixed call to "unicode.strip" in + exceptions.text_error_template which + is not Py3k compatible. [ticket:137] + +0.3.3 +- Added conditional to RichTraceback + such that if no traceback is passed + and sys.exc_info() has been reset, + the formatter just returns blank + for the "traceback" portion. + [ticket:135] + +- Fixed sometimes incorrect usage of + exc.__class__.__name__ + in html/text error templates when using + Python 2.4 [ticket:131] + +- Fixed broken @property decorator on + template.last_modified + +- Fixed error formatting when a stacktrace + line contains no line number, as in when + inside an eval/exec-generated function. + [ticket:132] + +- When a .py is being created, the tempfile + where the source is stored temporarily is + now made in the same directory as that of + the .py file. This ensures that the two + files share the same filesystem, thus + avoiding cross-filesystem synchronization + issues. Thanks to Charles Cazabon. + +0.3.2 +- Calling a def from the top, via + template.get_def(...).render() now checks the + argument signature the same way as it did in + 0.2.5, so that TypeError is not raised. + reopen of [ticket:116] + + +0.3.1 +- Fixed incorrect dir name in setup.py + [ticket:129] + +0.3 +- Python 2.3 support is dropped. [ticket:123] + +- Python 3 support is added ! See README.py3k + for installation and testing notes. + [ticket:119] + +- Unit tests now run with nose. [ticket:127] + +- Source code escaping has been simplified. + In particular, module source files are now + generated with the Python "magic encoding + comment", and source code is passed through + mostly unescaped, except for that code which + is regenerated from parsed Python source. + This fixes usage of unicode in + <%namespace:defname> tags. [ticket:99] + +- RichTraceback(), html_error_template().render(), + text_error_template().render() now accept "error" + and "traceback" as optional arguments, and + these are now actually used. [ticket:122] + +- The exception output generated when + format_exceptions=True will now be as a Python + unicode if it occurred during render_unicode(), + or an encoded string if during render(). + +- A percent sign can be emitted as the first + non-whitespace character on a line by escaping + it as in "%%". [ticket:112] + +- Template accepts empty control structure, i.e. + % if: %endif, etc. [ticket:94] + +- The <%page args> tag can now be used in a base + inheriting template - the full set of render() + arguments are passed down through the inherits + chain. Undeclared arguments go into **pageargs + as usual. [ticket:116] + +- defs declared within a <%namespace> section, an + uncommon feature, have been improved. The defs + no longer get doubly-rendered in the body() scope, + and now allow local variable assignment without + breakage. [ticket:109] + +- Windows paths are handled correctly if a Template + is passed only an absolute filename (i.e. with c: + drive etc.) and no URI - the URI is converted + to a forward-slash path and module_directory + is treated as a windows path. [ticket:128] + +- TemplateLookup raises TopLevelLookupException for + a given path that is a directory, not a filename, + instead of passing through to the template to + generate IOError. [ticket:73] + +0.2.6 + +- Fix mako function decorators to preserve the + original function's name in all cases. Patch + from Scott Torborg. + +- Support the <%namespacename:defname> syntax in + the babel extractor. [ticket:118] + +- Further fixes to unicode handling of .py files with the + html_error_template. [ticket:88] + +0.2.5 +- Added a "decorator" kw argument to <%def>, + allows custom decoration functions to wrap + rendering callables. Mainly intended for + custom caching algorithms, not sure what + other uses there may be (but there may be). + Examples are in the "filtering" docs. + +- When Mako creates subdirectories in which + to store templates, it uses the more + permissive mode of 0775 instead of 0750, + helping out with certain multi-process + scenarios. Note that the mode is always + subject to the restrictions of the existing + umask. [ticket:101] + +- Fixed namespace.__getattr__() to raise + AttributeError on attribute not found + instead of RuntimeError. [ticket:104] + +- Added last_modified accessor to Template, + returns the time.time() when the module + was created. [ticket:97] + +- Fixed lexing support for whitespace + around '=' sign in defs. [ticket:102] + +- Removed errant "lower()" in the lexer which + was causing tags to compile with + case-insensitive names, thus messing up + custom <%call> names. [ticket:108] + +- added "mako.__version__" attribute to + the base module. [ticket:110] + +0.2.4 +- Fixed compatibility with Jython 2.5b1. + +0.2.3 +- the <%namespacename:defname> syntax described at + http://techspot.zzzeek.org/?p=28 has now + been added as a built in syntax, and is recommended + as a more modern syntax versus <%call expr="expression">. + The %call tag itself will always remain, + with <%namespacename:defname> presenting a more HTML-like + alternative to calling defs, both plain and + nested. Many examples of the new syntax are in the + "Calling a def with embedded content" section + of the docs. + +- added support for Jython 2.5. + +- cache module now uses Beaker's CacheManager + object directly, so that all cache types are included. + memcached is available as both "ext:memcached" and + "memcached", the latter for backwards compatibility. + +- added "cache" accessor to Template, Namespace. + e.g. ${local.cache.get('somekey')} or + template.cache.invalidate_body() + +- added "cache_enabled=True" flag to Template, + TemplateLookup. Setting this to False causes cache + operations to "pass through" and execute every time; + this flag should be integrated in Pylons with its own + cache_enabled configuration setting. + +- the Cache object now supports invalidate_def(name), + invalidate_body(), invalidate_closure(name), + invalidate(key), which will remove the given key + from the cache, if it exists. The cache arguments + (i.e. storage type) are derived from whatever has + been already persisted for that template. + [ticket:92] + +- For cache changes to work fully, Beaker 1.1 is required. + 1.0.1 and up will work as well with the exception of + cache expiry. Note that Beaker 1.1 is **required** + for applications which use dynamically generated keys, + since previous versions will permanently store state in memory + for each individual key, thus consuming all available + memory for an arbitrarily large number of distinct + keys. + +- fixed bug whereby an <%included> template with + <%page> args named the same as a __builtin__ would not + honor the default value specified in <%page> [ticket:93] + +- fixed the html_error_template not handling tracebacks from + normal .py files with a magic encoding comment [ticket:88] + +- RichTraceback() now accepts an optional traceback object + to be used in place of sys.exc_info()[2]. html_error_template() + and text_error_template() accept an optional + render()-time argument "traceback" which is passed to the + RichTraceback object. + +- added ModuleTemplate class, which allows the construction + of a Template given a Python module generated by a previous + Template. This allows Python modules alone to be used + as templates with no compilation step. Source code + and template source are optional but allow error reporting + to work correctly. + +- fixed Python 2.3 compat. in mako.pyparser [ticket:90] + +- fix Babel 0.9.3 compatibility; stripping comment tags is now + optional (and enabled by default). + + +0.2.2 +- cached blocks now use the current context when rendering +an expired section, instead of the original context +passed in [ticket:87] +- fixed a critical issue regarding caching, whereby +a cached block would raise an error when called within a +cache-refresh operation that was initiated after the +initiating template had completed rendering. + +0.2.1 +- fixed bug where 'output_encoding' parameter would prevent +render_unicode() from returning a unicode object. +- bumped magic number, which forces template recompile for +this version (fixes incompatible compile symbols from 0.1 +series). +- added a few docs for cache options, specifically those that +help with memcached. + +0.2.0 +- Speed improvements (as though we needed them, but people + contributed and there you go): + + - added "bytestring passthru" mode, via + `disable_unicode=True` argument passed to Template or + TemplateLookup. All unicode-awareness and filtering is + turned off, and template modules are generated with + the appropriate magic encoding comment. In this mode, + template expressions can only receive raw bytestrings + or Unicode objects which represent straight ASCII, and + render_unicode() may not be used if multibyte + characters are present. When enabled, speed + improvement around 10-20%. [ticket:77] (courtesy + anonymous guest) + + - inlined the "write" function of Context into a local + template variable. This affords a 12-30% speedup in + template render time. (idea courtesy same anonymous + guest) [ticket:76] + +- New Features, API changes: + + - added "attr" accessor to namespaces. Returns + attributes configured as module level attributes, i.e. + within <%! %> sections. [ticket:62] i.e.: + + # somefile.html + <%! + foo = 27 + %> + + # some other template + <%namespace name="myns" file="somefile.html"/> + ${myns.attr.foo} + + The slight backwards incompatibility here is, you + can't have namespace defs named "attr" since the + "attr" descriptor will occlude it. + + - cache_key argument can now render arguments passed + directly to the %page or %def, i.e. <%def + name="foo(x)" cached="True" cache_key="${x}"/> + [ticket:78] + + - some functions on Context are now private: + _push_buffer(), _pop_buffer(), + caller_stack._push_frame(), caller_stack._pop_frame(). + + - added a runner script "mako-render" which renders + standard input as a template to stdout [ticket:81] + [ticket:56] + +- Bugfixes: + - can now use most names from __builtins__ as variable + names without explicit declaration (i.e. 'id', + 'exception', 'range', etc.) [ticket:83] [ticket:84] + + - can also use builtin names as local variable names + (i.e. dict, locals) (came from fix for [ticket:84]) + + - fixed bug in python generation when variable names are + used with identifiers like "else", "finally", etc. + inside them [ticket:68] + + - fixed codegen bug which occured when using <%page> + level caching, combined with an expression-based + cache_key, combined with the usage of <%namespace + import="*"/> - fixed lexer exceptions not cleaning up + temporary files, which could lead to a maximum number + of file descriptors used in the process [ticket:69] + + - fixed issue with inline format_exceptions that was + producing blank exception pages when an inheriting + template is present [ticket:71] + + - format_exceptions will apply the encoding options of + html_error_template() to the buffered output + + - rewrote the "whitespace adjuster" function to work + with more elaborate combinations of quotes and + comments [ticket:75] + +0.1.10 +- fixed propagation of 'caller' such that nested %def calls + within a <%call> tag's argument list propigates 'caller' + to the %call function itself (propigates to the inner + calls too, this is a slight side effect which previously + existed anyway) +- fixed bug where local.get_namespace() could put an + incorrect "self" in the current context +- fixed another namespace bug where the namespace functions + did not have access to the correct context containing + their 'self' and 'parent' + +0.1.9 +- filters.Decode filter can also accept a non-basestring +object and will call str() + unicode() on it [ticket:47] +- comments can be placed at the end of control lines, +i.e. if foo: # a comment, [ticket:53], thanks to +Paul Colomiets +- fixed expressions and page tag arguments and with embedded +newlines in CRLF templates, follow up to [ticket:16], thanks +Eric Woroshow +- added an IOError catch for source file not found in RichTraceback +exception reporter [ticket:51] + +0.1.8 +- variable names declared in render methods by internal +codegen prefixed by "__M_" to prevent name collisions +with user code +- added a Babel (http://babel.edgewall.org/) extractor entry +point, allowing extraction of gettext messages directly from +mako templates via Babel [ticket:45] +- fix to turbogears plugin to work with dot-separated names +(i.e. load_template('foo.bar')). also takes file extension +as a keyword argument (default is 'mak'). +- more tg fix: fixed [ticket:35], allowing string-based +templates with tgplugin even if non-compatible args were sent + +0.1.7 +- one small fix to the unit tests to support python 2.3 +- a slight hack to how cache.py detects Beaker's memcached, +works around unexplained import behavior observed on some +python 2.3 installations + +0.1.6 +- caching is now supplied directly by Beaker, which has + all of MyghtyUtils merged into it now. The latest Beaker + (0.7.1) also fixes a bug related to how Mako was using the + cache API. +- fix to module_directory path generation when the path is "./" + [ticket:34] +- TGPlugin passes options to string-based templates [ticket:35] +- added an explicit stack frame step to template runtime, which + allows much simpler and hopefully bug-free tracking of 'caller', + fixes #28 +- if plain Python defs are used with <%call>, a decorator + @runtime.supports_callable exists to ensure that the "caller" + stack is properly handled for the def. +- fix to RichTraceback and exception reporting to get template + source code as a unicode object #37 +- html_error_template includes options "full=True", "css=True" + which control generation of HTML tags, CSS [ticket:39] +- added the 'encoding_errors' parameter to Template/TemplateLookup + for specifying the error handler associated with encoding to + 'output_encoding' [ticket:40] +- the Template returned by html_error_template now defaults to + output_encoding=sys.getdefaultencoding(), + encoding_errors='htmlentityreplace' [ticket:37] +- control lines, i.e. % lines, support backslashes to continue long + lines (#32) +- fixed codegen bug when defining <%def> within <%call> within <%call> +- leading utf-8 BOM in template files is honored according to pep-0263 + +0.1.5 +- AST expression generation - added in just about everything + expression-wise from the AST module [ticket:26] +- AST parsing, properly detects imports of the form "import foo.bar" + [ticket:27] +- fix to lexing of <%docs> tag nested in other tags +- fix to context-arguments inside of <%include> tag which broke +during 0.1.4 [ticket:29] +- added "n" filter, disables *all* filters normally applied to an expression +via <%page> or default_filters (but not those within the filter) +- added buffer_filters argument, defines filters applied to the return value +of buffered/cached/filtered %defs, after all filters defined with the %def +itself have been applied. allows the creation of default expression filters +that let the output of return-valued %defs "opt out" of that filtering +via passing special attributes or objects. + +0.1.4 +- got defs-within-defs to be cacheable +- fixes to code parsing/whitespace adjusting where plain python comments + may contain quote characters [ticket:23] +- fix to variable scoping for identifiers only referenced within + functions +- added a path normalization step to lookup so URIs like + "/foo/bar/../etc/../foo" pre-process the ".." tokens before checking + the filesystem +- fixed/improved "caller" semantics so that undefined caller is + "UNDEFINED", propigates __nonzero__ method so it evaulates to False if + not present, True otherwise. this way you can say % if caller:\n + ${caller.body()}\n% endif +- <%include> has an "args" attribute that can pass arguments to the + called template (keyword arguments only, must be declared in that + page's <%page> tag.) +- <%include> plus arguments is also programmatically available via + self.include_file(, **kwargs) +- further escaping added for multibyte expressions in %def, %call + attributes [ticket:24] + + +0.1.3 +- ***Small Syntax Change*** - the single line comment character is now +*two* hash signs, i.e. "## this is a comment". This avoids a common +collection with CSS selectors. +- the magic "coding" comment (i.e. # coding:utf-8) will still work with +either one "#" sign or two for now; two is preferred going forward, i.e. +## coding:. +- new multiline comment form: "<%doc> a comment " +- UNDEFINED evaluates to False +- improvement to scoping of "caller" variable when using <%call> tag +- added lexer error for unclosed control-line (%) line +- added "preprocessor" argument to Template, TemplateLookup - is a single + callable or list of callables which will be applied to the template text + before lexing. given the text as an argument, returns the new text. +- added mako.ext.preprocessors package, contains one preprocessor so far: + 'convert_comments', which will convert single # comments to the new ## + format + +0.1.2 +- fix to parsing of code/expression blocks to insure that non-ascii + characters, combined with a template that indicates a non-standard + encoding, are expanded into backslash-escaped glyphs before being AST + parsed [ticket:11] +- all template lexing converts the template to unicode first, to + immediately catch any encoding issues and ensure internal unicode + representation. +- added module_filename argument to Template to allow specification of a + specific module file +- added modulename_callable to TemplateLookup to allow a function to + determine module filenames (takes filename, uri arguments). used for + [ticket:14] +- added optional input_encoding flag to Template, to allow sending a + unicode() object with no magic encoding comment +- "expression_filter" argument in <%page> applies only to expressions +- added "default_filters" argument to Template, TemplateLookup. applies only + to expressions, gets prepended to "expression_filter" arg from <%page>. + defaults to ["unicode"], so that all expressions get stringified into u'' + by default (this is what Mako already does). By setting to [], expressions + are passed through raw. +- added "imports" argument to Template, TemplateLookup. so you can predefine + a list of import statements at the top of the template. can be used in + conjunction with default_filters. +- support for CRLF templates...whoops ! welcome to all the windows users. + [ticket:16] +- small fix to local variable propigation for locals that are conditionally + declared +- got "top level" def calls to work, i.e. template.get_def("somedef").render() + +0.1.1 +- buffet plugin supports string-based templates, allows ToscaWidgets to work + [ticket:8] +- AST parsing fixes: fixed TryExcept identifier parsing +- removed textmate tmbundle from contrib and into separate SVN location; + windows users cant handle those files, setuptools not very good at + "pruning" certain directories +- fix so that "cache_timeout" parameter is propigated +- fix to expression filters so that string conversion (actually unicode) + properly occurs before filtering +- better error message when a lookup is attempted with a template that has no + lookup +- implemented "module" attribute for namespace +- fix to code generation to correctly track multiple defs with the same name +- "directories" can be passed to TemplateLookup as a scalar in which case it + gets converted to a list [ticket:9] + +0.1.0 + +Initial release. diff --git a/lib/mako-0.7.2/LICENSE b/lib/mako-0.7.2/LICENSE new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/LICENSE @@ -0,0 +1,20 @@ +This is the MIT license: http://www.opensource.org/licenses/mit-license.php + +Copyright (C) 2006-2012 the Mako authors and contributors . +Mako is a trademark of Michael Bayer. + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/lib/mako-0.7.2/MANIFEST.in b/lib/mako-0.7.2/MANIFEST.in new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/MANIFEST.in @@ -0,0 +1,11 @@ +# any kind of "*" pulls in __init__.pyc files, +# so all extensions are explicit. + +recursive-include doc *.html *.css *.txt *.js *.png *.py Makefile *.rst *.mako +recursive-include examples *.py *.xml *.mako *.myt *.kid *.tmpl +recursive-include test *.py *.html *.mako + +include README* LICENSE distribute_setup.py ez_setup.py CHANGES* + +prune doc/build/output + diff --git a/lib/mako-0.7.2/Mako.egg-info/PKG-INFO b/lib/mako-0.7.2/Mako.egg-info/PKG-INFO new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/Mako.egg-info/PKG-INFO @@ -0,0 +1,71 @@ +Metadata-Version: 1.0 +Name: Mako +Version: 0.7.2 +Summary: A super-fast templating language that borrows the best ideas from the existing templating languages. +Home-page: http://www.makotemplates.org/ +Author: Mike Bayer +Author-email: mike at zzzcomputing.com +License: MIT +Description: ========================= + Mako Templates for Python + ========================= + + Mako is a template library written in Python. It provides a familiar, non-XML + syntax which compiles into Python modules for maximum performance. Mako's + syntax and API borrows from the best ideas of many others, including Django + templates, Cheetah, Myghty, and Genshi. Conceptually, Mako is an embedded + Python (i.e. Python Server Page) language, which refines the familiar ideas + of componentized layout and inheritance to produce one of the most + straightforward and flexible models available, while also maintaining close + ties to Python calling and scoping semantics. + + Nutshell + ======== + + :: + + <%inherit file="base.html"/> + <% + rows = [[v for v in range(0,10)] for row in range(0,10)] + %> + + % for row in rows: + ${makerow(row)} + % endfor +
+ + <%def name="makerow(row)"> + + % for name in row: + ${name}\ + % endfor + + + + Philosophy + =========== + + Python is a great scripting language. Don't reinvent the wheel...your templates can handle it ! + + Documentation + ============== + + See documentation for Mako at http://www.makotemplates.org/docs/ + + License + ======== + + Mako is licensed under an MIT-style license (see LICENSE). + Other incorporated projects may be licensed under different licenses. + All licenses allow for non-commercial and commercial use. + +Keywords: templates +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content diff --git a/lib/mako-0.7.2/Mako.egg-info/SOURCES.txt b/lib/mako-0.7.2/Mako.egg-info/SOURCES.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/Mako.egg-info/SOURCES.txt @@ -0,0 +1,171 @@ +CHANGES +LICENSE +MANIFEST.in +README.rst +distribute_setup.py +setup.cfg +setup.py +Mako.egg-info/PKG-INFO +Mako.egg-info/SOURCES.txt +Mako.egg-info/dependency_links.txt +Mako.egg-info/entry_points.txt +Mako.egg-info/not-zip-safe +Mako.egg-info/requires.txt +Mako.egg-info/top_level.txt +doc/caching.html +doc/defs.html +doc/filtering.html +doc/genindex.html +doc/index.html +doc/inheritance.html +doc/namespaces.html +doc/runtime.html +doc/search.html +doc/searchindex.js +doc/syntax.html +doc/unicode.html +doc/usage.html +doc/_sources/caching.txt +doc/_sources/defs.txt +doc/_sources/filtering.txt +doc/_sources/index.txt +doc/_sources/inheritance.txt +doc/_sources/namespaces.txt +doc/_sources/runtime.txt +doc/_sources/syntax.txt +doc/_sources/unicode.txt +doc/_sources/usage.txt +doc/_static/basic.css +doc/_static/comment-bright.png +doc/_static/comment-close.png +doc/_static/comment.png +doc/_static/default.css +doc/_static/docs.css +doc/_static/doctools.js +doc/_static/down-pressed.png +doc/_static/down.png +doc/_static/file.png +doc/_static/jquery.js +doc/_static/makoLogo.png +doc/_static/minus.png +doc/_static/plus.png +doc/_static/pygments.css +doc/_static/searchtools.js +doc/_static/sidebar.js +doc/_static/site.css +doc/_static/underscore.js +doc/_static/up-pressed.png +doc/_static/up.png +doc/_static/websupport.js +doc/build/Makefile +doc/build/caching.rst +doc/build/conf.py +doc/build/defs.rst +doc/build/filtering.rst +doc/build/index.rst +doc/build/inheritance.rst +doc/build/namespaces.rst +doc/build/runtime.rst +doc/build/syntax.rst +doc/build/unicode.rst +doc/build/usage.rst +doc/build/builder/__init__.py +doc/build/builder/builders.py +doc/build/builder/util.py +doc/build/static/docs.css +doc/build/static/makoLogo.png +doc/build/static/site.css +doc/build/templates/base.mako +doc/build/templates/genindex.mako +doc/build/templates/layout.mako +doc/build/templates/page.mako +doc/build/templates/rtd_layout.mako +doc/build/templates/search.mako +examples/bench/basic.py +examples/bench/cheetah/footer.tmpl +examples/bench/cheetah/header.tmpl +examples/bench/cheetah/template.tmpl +examples/bench/django/templatetags/__init__.py +examples/bench/django/templatetags/bench.py +examples/bench/kid/base.kid +examples/bench/kid/template.kid +examples/bench/myghty/base.myt +examples/bench/myghty/template.myt +examples/wsgi/run_wsgi.py +mako/__init__.py +mako/_ast_util.py +mako/ast.py +mako/cache.py +mako/codegen.py +mako/exceptions.py +mako/filters.py +mako/lexer.py +mako/lookup.py +mako/parsetree.py +mako/pygen.py +mako/pyparser.py +mako/runtime.py +mako/template.py +mako/util.py +mako/ext/__init__.py +mako/ext/autohandler.py +mako/ext/babelplugin.py +mako/ext/beaker_cache.py +mako/ext/preprocessors.py +mako/ext/pygmentplugin.py +mako/ext/turbogears.py +scripts/mako-render +test/__init__.py +test/sample_module_namespace.py +test/test_ast.py +test/test_babelplugin.py +test/test_block.py +test/test_cache.py +test/test_call.py +test/test_decorators.py +test/test_def.py +test/test_exceptions.py +test/test_filters.py +test/test_inheritance.py +test/test_lexer.py +test/test_lookup.py +test/test_loop.py +test/test_lru.py +test/test_namespace.py +test/test_pygen.py +test/test_template.py +test/test_tgplugin.py +test/test_util.py +test/util.py +test/foo/__init__.py +test/foo/test_ns.py +test/templates/badbom.html +test/templates/bom.html +test/templates/bommagic.html +test/templates/chs_unicode.html +test/templates/chs_unicode_py3k.html +test/templates/chs_utf8.html +test/templates/crlf.html +test/templates/gettext.mako +test/templates/index.html +test/templates/internationalization.html +test/templates/modtest.html +test/templates/read_unicode.html +test/templates/read_unicode_py3k.html +test/templates/runtimeerr.html +test/templates/runtimeerr_py3k.html +test/templates/unicode.html +test/templates/unicode_arguments.html +test/templates/unicode_arguments_py3k.html +test/templates/unicode_code.html +test/templates/unicode_code_py3k.html +test/templates/unicode_expr.html +test/templates/unicode_expr_py3k.html +test/templates/unicode_runtime_error.html +test/templates/unicode_syntax_error.html +test/templates/foo/modtest.html.py +test/templates/othersubdir/foo.html +test/templates/subdir/incl.html +test/templates/subdir/index.html +test/templates/subdir/modtest.html +test/templates/subdir/foo/modtest.html.py \ No newline at end of file diff --git a/lib/mako-0.7.2/Mako.egg-info/dependency_links.txt b/lib/mako-0.7.2/Mako.egg-info/dependency_links.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/Mako.egg-info/dependency_links.txt @@ -0,0 +1,1 @@ + diff --git a/lib/mako-0.7.2/Mako.egg-info/entry_points.txt b/lib/mako-0.7.2/Mako.egg-info/entry_points.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/Mako.egg-info/entry_points.txt @@ -0,0 +1,14 @@ + + [python.templating.engines] + mako = mako.ext.turbogears:TGPlugin + + [pygments.lexers] + mako = mako.ext.pygmentplugin:MakoLexer + html+mako = mako.ext.pygmentplugin:MakoHtmlLexer + xml+mako = mako.ext.pygmentplugin:MakoXmlLexer + js+mako = mako.ext.pygmentplugin:MakoJavascriptLexer + css+mako = mako.ext.pygmentplugin:MakoCssLexer + + [babel.extractors] + mako = mako.ext.babelplugin:extract + \ No newline at end of file diff --git a/lib/mako-0.7.2/Mako.egg-info/not-zip-safe b/lib/mako-0.7.2/Mako.egg-info/not-zip-safe new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/Mako.egg-info/not-zip-safe @@ -0,0 +1,1 @@ + diff --git a/lib/mako-0.7.2/Mako.egg-info/requires.txt b/lib/mako-0.7.2/Mako.egg-info/requires.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/Mako.egg-info/requires.txt @@ -0,0 +1,4 @@ +MarkupSafe>=0.9.2 + +[beaker] +Beaker>=1.1 \ No newline at end of file diff --git a/lib/mako-0.7.2/Mako.egg-info/top_level.txt b/lib/mako-0.7.2/Mako.egg-info/top_level.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/Mako.egg-info/top_level.txt @@ -0,0 +1,1 @@ +mako diff --git a/lib/mako-0.7.2/PKG-INFO b/lib/mako-0.7.2/PKG-INFO new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/PKG-INFO @@ -0,0 +1,71 @@ +Metadata-Version: 1.0 +Name: Mako +Version: 0.7.2 +Summary: A super-fast templating language that borrows the best ideas from the existing templating languages. +Home-page: http://www.makotemplates.org/ +Author: Mike Bayer +Author-email: mike at zzzcomputing.com +License: MIT +Description: ========================= + Mako Templates for Python + ========================= + + Mako is a template library written in Python. It provides a familiar, non-XML + syntax which compiles into Python modules for maximum performance. Mako's + syntax and API borrows from the best ideas of many others, including Django + templates, Cheetah, Myghty, and Genshi. Conceptually, Mako is an embedded + Python (i.e. Python Server Page) language, which refines the familiar ideas + of componentized layout and inheritance to produce one of the most + straightforward and flexible models available, while also maintaining close + ties to Python calling and scoping semantics. + + Nutshell + ======== + + :: + + <%inherit file="base.html"/> + <% + rows = [[v for v in range(0,10)] for row in range(0,10)] + %> + + % for row in rows: + ${makerow(row)} + % endfor +
+ + <%def name="makerow(row)"> + + % for name in row: + ${name}\ + % endfor + + + + Philosophy + =========== + + Python is a great scripting language. Don't reinvent the wheel...your templates can handle it ! + + Documentation + ============== + + See documentation for Mako at http://www.makotemplates.org/docs/ + + License + ======== + + Mako is licensed under an MIT-style license (see LICENSE). + Other incorporated projects may be licensed under different licenses. + All licenses allow for non-commercial and commercial use. + +Keywords: templates +Platform: UNKNOWN +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Web Environment +Classifier: Intended Audience :: Developers +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content diff --git a/lib/mako-0.7.2/README.rst b/lib/mako-0.7.2/README.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/README.rst @@ -0,0 +1,52 @@ +========================= +Mako Templates for Python +========================= + +Mako is a template library written in Python. It provides a familiar, non-XML +syntax which compiles into Python modules for maximum performance. Mako's +syntax and API borrows from the best ideas of many others, including Django +templates, Cheetah, Myghty, and Genshi. Conceptually, Mako is an embedded +Python (i.e. Python Server Page) language, which refines the familiar ideas +of componentized layout and inheritance to produce one of the most +straightforward and flexible models available, while also maintaining close +ties to Python calling and scoping semantics. + +Nutshell +======== + +:: + + <%inherit file="base.html"/> + <% + rows = [[v for v in range(0,10)] for row in range(0,10)] + %> + + % for row in rows: + ${makerow(row)} + % endfor +
+ + <%def name="makerow(row)"> + + % for name in row: + ${name}\ + % endfor + + + +Philosophy +=========== + +Python is a great scripting language. Don't reinvent the wheel...your templates can handle it ! + +Documentation +============== + +See documentation for Mako at http://www.makotemplates.org/docs/ + +License +======== + +Mako is licensed under an MIT-style license (see LICENSE). +Other incorporated projects may be licensed under different licenses. +All licenses allow for non-commercial and commercial use. diff --git a/lib/mako-0.7.2/distribute_setup.py b/lib/mako-0.7.2/distribute_setup.py new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/distribute_setup.py @@ -0,0 +1,485 @@ +#!python +"""Bootstrap distribute installation + +If you want to use setuptools in your package's setup.py, just include this +file in the same directory with it, and add this to the top of your setup.py:: + + from distribute_setup import use_setuptools + use_setuptools() + +If you want to require a specific version of setuptools, set a download +mirror, or use an alternate download directory, you can do so by supplying +the appropriate options to ``use_setuptools()``. + +This file can also be run as a script to install or upgrade setuptools. +""" +import os +import sys +import time +import fnmatch +import tempfile +import tarfile +from distutils import log + +try: + from site import USER_SITE +except ImportError: + USER_SITE = None + +try: + import subprocess + + def _python_cmd(*args): + args = (sys.executable,) + args + return subprocess.call(args) == 0 + +except ImportError: + # will be used for python 2.3 + def _python_cmd(*args): + args = (sys.executable,) + args + # quoting arguments if windows + if sys.platform == 'win32': + def quote(arg): + if ' ' in arg: + return '"%s"' % arg + return arg + args = [quote(arg) for arg in args] + return os.spawnl(os.P_WAIT, sys.executable, *args) == 0 + +DEFAULT_VERSION = "0.6.13" +DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/" +SETUPTOOLS_FAKED_VERSION = "0.6c11" + +SETUPTOOLS_PKG_INFO = """\ +Metadata-Version: 1.0 +Name: setuptools +Version: %s +Summary: xxxx +Home-page: xxx +Author: xxx +Author-email: xxx +License: xxx +Description: xxx +""" % SETUPTOOLS_FAKED_VERSION + + +def _install(tarball): + # extracting the tarball + tmpdir = tempfile.mkdtemp() + log.warn('Extracting in %s', tmpdir) + old_wd = os.getcwd() + try: + os.chdir(tmpdir) + tar = tarfile.open(tarball) + _extractall(tar) + tar.close() + + # going in the directory + subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) + os.chdir(subdir) + log.warn('Now working in %s', subdir) + + # installing + log.warn('Installing Distribute') + if not _python_cmd('setup.py', 'install'): + log.warn('Something went wrong during the installation.') + log.warn('See the error message above.') + finally: + os.chdir(old_wd) + + +def _build_egg(egg, tarball, to_dir): + # extracting the tarball + tmpdir = tempfile.mkdtemp() + log.warn('Extracting in %s', tmpdir) + old_wd = os.getcwd() + try: + os.chdir(tmpdir) + tar = tarfile.open(tarball) + _extractall(tar) + tar.close() + + # going in the directory + subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) + os.chdir(subdir) + log.warn('Now working in %s', subdir) + + # building an egg + log.warn('Building a Distribute egg in %s', to_dir) + _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) + + finally: + os.chdir(old_wd) + # returning the result + log.warn(egg) + if not os.path.exists(egg): + raise IOError('Could not build the egg.') + + +def _do_download(version, download_base, to_dir, download_delay): + egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg' + % (version, sys.version_info[0], sys.version_info[1])) + if not os.path.exists(egg): + tarball = download_setuptools(version, download_base, + to_dir, download_delay) + _build_egg(egg, tarball, to_dir) + sys.path.insert(0, egg) + import setuptools + setuptools.bootstrap_install_from = egg + + +def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=os.curdir, download_delay=15, no_fake=True): + # making sure we use the absolute path + to_dir = os.path.abspath(to_dir) + was_imported = 'pkg_resources' in sys.modules or \ + 'setuptools' in sys.modules + try: + try: + import pkg_resources + if not hasattr(pkg_resources, '_distribute'): + if not no_fake: + _fake_setuptools() + raise ImportError + except ImportError: + return _do_download(version, download_base, to_dir, download_delay) + try: + pkg_resources.require("distribute>="+version) + return + except pkg_resources.VersionConflict: + e = sys.exc_info()[1] + if was_imported: + sys.stderr.write( + "The required version of distribute (>=%s) is not available,\n" + "and can't be installed while this script is running. Please\n" + "install a more recent version first, using\n" + "'easy_install -U distribute'." + "\n\n(Currently using %r)\n" % (version, e.args[0])) + sys.exit(2) + else: + del pkg_resources, sys.modules['pkg_resources'] # reload ok + return _do_download(version, download_base, to_dir, + download_delay) + except pkg_resources.DistributionNotFound: + return _do_download(version, download_base, to_dir, + download_delay) + finally: + if not no_fake: + _create_fake_setuptools_pkg_info(to_dir) + +def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=os.curdir, delay=15): + """Download distribute from a specified location and return its filename + + `version` should be a valid distribute version number that is available + as an egg for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download + attempt. + """ + # making sure we use the absolute path + to_dir = os.path.abspath(to_dir) + try: + from urllib.request import urlopen + except ImportError: + from urllib2 import urlopen + tgz_name = "distribute-%s.tar.gz" % version + url = download_base + tgz_name + saveto = os.path.join(to_dir, tgz_name) + src = dst = None + if not os.path.exists(saveto): # Avoid repeated downloads + try: + log.warn("Downloading %s", url) + src = urlopen(url) + # Read/write all in one block, so we don't create a corrupt file + # if the download is interrupted. + data = src.read() + dst = open(saveto, "wb") + dst.write(data) + finally: + if src: + src.close() + if dst: + dst.close() + return os.path.realpath(saveto) + +def _no_sandbox(function): + def __no_sandbox(*args, **kw): + try: + from setuptools.sandbox import DirectorySandbox + if not hasattr(DirectorySandbox, '_old'): + def violation(*args): + pass + DirectorySandbox._old = DirectorySandbox._violation + DirectorySandbox._violation = violation + patched = True + else: + patched = False + except ImportError: + patched = False + + try: + return function(*args, **kw) + finally: + if patched: + DirectorySandbox._violation = DirectorySandbox._old + del DirectorySandbox._old + + return __no_sandbox + +def _patch_file(path, content): + """Will backup the file then patch it""" + existing_content = open(path).read() + if existing_content == content: + # already patched + log.warn('Already patched.') + return False + log.warn('Patching...') + _rename_path(path) + f = open(path, 'w') + try: + f.write(content) + finally: + f.close() + return True + +_patch_file = _no_sandbox(_patch_file) + +def _same_content(path, content): + return open(path).read() == content + +def _rename_path(path): + new_name = path + '.OLD.%s' % time.time() + log.warn('Renaming %s into %s', path, new_name) + os.rename(path, new_name) + return new_name + +def _remove_flat_installation(placeholder): + if not os.path.isdir(placeholder): + log.warn('Unkown installation at %s', placeholder) + return False + found = False + for file in os.listdir(placeholder): + if fnmatch.fnmatch(file, 'setuptools*.egg-info'): + found = True + break + if not found: + log.warn('Could not locate setuptools*.egg-info') + return + + log.warn('Removing elements out of the way...') + pkg_info = os.path.join(placeholder, file) + if os.path.isdir(pkg_info): + patched = _patch_egg_dir(pkg_info) + else: + patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO) + + if not patched: + log.warn('%s already patched.', pkg_info) + return False + # now let's move the files out of the way + for element in ('setuptools', 'pkg_resources.py', 'site.py'): + element = os.path.join(placeholder, element) + if os.path.exists(element): + _rename_path(element) + else: + log.warn('Could not find the %s element of the ' + 'Setuptools distribution', element) + return True + +_remove_flat_installation = _no_sandbox(_remove_flat_installation) + +def _after_install(dist): + log.warn('After install bootstrap.') + placeholder = dist.get_command_obj('install').install_purelib + _create_fake_setuptools_pkg_info(placeholder) + +def _create_fake_setuptools_pkg_info(placeholder): + if not placeholder or not os.path.exists(placeholder): + log.warn('Could not find the install location') + return + pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1]) + setuptools_file = 'setuptools-%s-py%s.egg-info' % \ + (SETUPTOOLS_FAKED_VERSION, pyver) + pkg_info = os.path.join(placeholder, setuptools_file) + if os.path.exists(pkg_info): + log.warn('%s already exists', pkg_info) + return + + log.warn('Creating %s', pkg_info) + f = open(pkg_info, 'w') + try: + f.write(SETUPTOOLS_PKG_INFO) + finally: + f.close() + + pth_file = os.path.join(placeholder, 'setuptools.pth') + log.warn('Creating %s', pth_file) + f = open(pth_file, 'w') + try: + f.write(os.path.join(os.curdir, setuptools_file)) + finally: + f.close() + +_create_fake_setuptools_pkg_info = _no_sandbox(_create_fake_setuptools_pkg_info) + +def _patch_egg_dir(path): + # let's check if it's already patched + pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') + if os.path.exists(pkg_info): + if _same_content(pkg_info, SETUPTOOLS_PKG_INFO): + log.warn('%s already patched.', pkg_info) + return False + _rename_path(path) + os.mkdir(path) + os.mkdir(os.path.join(path, 'EGG-INFO')) + pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO') + f = open(pkg_info, 'w') + try: + f.write(SETUPTOOLS_PKG_INFO) + finally: + f.close() + return True + +_patch_egg_dir = _no_sandbox(_patch_egg_dir) + +def _before_install(): + log.warn('Before install bootstrap.') + _fake_setuptools() + + +def _under_prefix(location): + if 'install' not in sys.argv: + return True + args = sys.argv[sys.argv.index('install')+1:] + for index, arg in enumerate(args): + for option in ('--root', '--prefix'): + if arg.startswith('%s=' % option): + top_dir = arg.split('root=')[-1] + return location.startswith(top_dir) + elif arg == option: + if len(args) > index: + top_dir = args[index+1] + return location.startswith(top_dir) + if arg == '--user' and USER_SITE is not None: + return location.startswith(USER_SITE) + return True + + +def _fake_setuptools(): + log.warn('Scanning installed packages') + try: + import pkg_resources + except ImportError: + # we're cool + log.warn('Setuptools or Distribute does not seem to be installed.') + return + ws = pkg_resources.working_set + try: + setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools', + replacement=False)) + except TypeError: + # old distribute API + setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools')) + + if setuptools_dist is None: + log.warn('No setuptools distribution found') + return + # detecting if it was already faked + setuptools_location = setuptools_dist.location + log.warn('Setuptools installation detected at %s', setuptools_location) + + # if --root or --preix was provided, and if + # setuptools is not located in them, we don't patch it + if not _under_prefix(setuptools_location): + log.warn('Not patching, --root or --prefix is installing Distribute' + ' in another location') + return + + # let's see if its an egg + if not setuptools_location.endswith('.egg'): + log.warn('Non-egg installation') + res = _remove_flat_installation(setuptools_location) + if not res: + return + else: + log.warn('Egg installation') + pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO') + if (os.path.exists(pkg_info) and + _same_content(pkg_info, SETUPTOOLS_PKG_INFO)): + log.warn('Already patched.') + return + log.warn('Patching...') + # let's create a fake egg replacing setuptools one + res = _patch_egg_dir(setuptools_location) + if not res: + return + log.warn('Patched done.') + _relaunch() + + +def _relaunch(): + log.warn('Relaunching...') + # we have to relaunch the process + # pip marker to avoid a relaunch bug + if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']: + sys.argv[0] = 'setup.py' + args = [sys.executable] + sys.argv + sys.exit(subprocess.call(args)) + + +def _extractall(self, path=".", members=None): + """Extract all members from the archive to the current working + directory and set owner, modification time and permissions on + directories afterwards. `path' specifies a different directory + to extract to. `members' is optional and must be a subset of the + list returned by getmembers(). + """ + import copy + import operator + from tarfile import ExtractError + directories = [] + + if members is None: + members = self + + for tarinfo in members: + if tarinfo.isdir(): + # Extract directories with a safe mode. + directories.append(tarinfo) + tarinfo = copy.copy(tarinfo) + tarinfo.mode = 448 # decimal for oct 0700 + self.extract(tarinfo, path) + + # Reverse sort directories. + if sys.version_info < (2, 4): + def sorter(dir1, dir2): + return cmp(dir1.name, dir2.name) + directories.sort(sorter) + directories.reverse() + else: + directories.sort(key=operator.attrgetter('name'), reverse=True) + + # Set correct owner, mtime and filemode on directories. + for tarinfo in directories: + dirpath = os.path.join(path, tarinfo.name) + try: + self.chown(tarinfo, dirpath) + self.utime(tarinfo, dirpath) + self.chmod(tarinfo, dirpath) + except ExtractError: + e = sys.exc_info()[1] + if self.errorlevel > 1: + raise + else: + self._dbg(1, "tarfile: %s" % e) + + +def main(argv, version=DEFAULT_VERSION): + """Install or upgrade setuptools and EasyInstall""" + tarball = download_setuptools() + _install(tarball) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/lib/mako-0.7.2/doc/_sources/caching.txt b/lib/mako-0.7.2/doc/_sources/caching.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/caching.txt @@ -0,0 +1,393 @@ +.. _caching_toplevel: + +======= +Caching +======= + +Any template or component can be cached using the ``cache`` +argument to the ``<%page>``, ``<%def>`` or ``<%block>`` directives: + +.. sourcecode:: mako + + <%page cached="True"/> + + template text + +The above template, after being executed the first time, will +store its content within a cache that by default is scoped +within memory. Subsequent calls to the template's :meth:`~.Template.render` +method will return content directly from the cache. When the +:class:`.Template` object itself falls out of scope, its corresponding +cache is garbage collected along with the template. + +By default, caching requires that the `Beaker `_ package be installed on the +system, however the mechanism of caching can be customized to use +any third party or user defined system -- see :ref:`cache_plugins`. + +In addition to being available on the ``<%page>`` tag, the caching flag and all +its options can be used with the ``<%def>`` tag as well: + +.. sourcecode:: mako + + <%def name="mycomp" cached="True" cache_timeout="60"> + other text + + +... and equivalently with the ``<%block>`` tag, anonymous or named: + +.. sourcecode:: mako + + <%block cached="True" cache_timeout="60"> + other text + + +Cache Arguments +=============== + +Mako has two cache arguments available on tags that are +available in all cases. The rest of the arguments +available are specific to a backend. + +The two generic tags arguments are: + +* ``cached="True"`` - enable caching for this ``<%page>``, + ``<%def>``, or ``<%block>``. +* ``cache_key`` - the "key" used to uniquely identify this content + in the cache. Usually, this key is chosen automatically + based on the name of the rendering callable (i.e. ``body`` + when used in ``<%page>``, the name of the def when using ``<%def>``, + the explicit or internally-generated name when using ``<%block>``). + Using the ``cache_key`` parameter, the key can be overridden + using a fixed or programmatically generated value. + + For example, here's a page + that caches any page which inherits from it, based on the + filename of the calling template: + + .. sourcecode:: mako + + <%page cached="True" cache_key="${self.filename}"/> + + ${next.body()} + + ## rest of template + +On a :class:`.Template` or :class:`.TemplateLookup`, the +caching can be configured using these arguments: + +* ``cache_enabled`` - Setting this + to ``False`` will disable all caching functionality + when the template renders. Defaults to ``True``. + e.g.: + + .. sourcecode:: python + + lookup = TemplateLookup( + directories='/path/to/templates', + cache_enabled = False + ) + +* ``cache_impl`` - The string name of the cache backend + to use. This defaults to ``'beaker'``, which has historically + been the only cache backend supported by Mako. + + .. versionadded:: 0.6.0 + + For example, here's how to use the upcoming + `dogpile.cache `_ + backend: + + .. sourcecode:: python + + lookup = TemplateLookup( + directories='/path/to/templates', + cache_impl = 'dogpile.cache', + cache_args = {'regions':my_dogpile_regions} + ) + +* ``cache_args`` - A dictionary of cache parameters that + will be consumed by the cache backend. See + :ref:`beaker_backend` for examples. + + .. versionadded:: 0.6.0 + +Backend-Specific Cache Arguments +-------------------------------- + +The ``<%page>``, ``<%def>``, and ``<%block>`` tags +accept any named argument that starts with the prefix ``"cache_"``. +Those arguments are then packaged up and passed along to the +underlying caching implementation, minus the ``"cache_"`` prefix. + +The actual arguments understood are determined by the backend. + +* :ref:`beaker_backend` - Includes arguments understood by + Beaker. +* :ref:`dogpile.cache_backend` - Includes arguments understood by + dogpile.cache. + +.. _beaker_backend: + +Using the Beaker Cache Backend +------------------------------ + +When using Beaker, new implementations will want to make usage +of **cache regions** so that cache configurations can be maintained +externally to templates. These configurations live under +named "regions" that can be referred to within templates themselves. + +.. versionadded:: 0.6.0 + Support for Beaker cache regions. + +For example, suppose we would like two regions. One is a "short term" +region that will store content in a memory-based dictionary, +expiring after 60 seconds. The other is a Memcached region, +where values should expire in five minutes. To configure +our :class:`.TemplateLookup`, first we get a handle to a +:class:`beaker.cache.CacheManager`: + +.. sourcecode:: python + + from beaker.cache import CacheManager + + manager = CacheManager(cache_regions={ + 'short_term':{ + 'type': 'memory', + 'expire': 60 + }, + 'long_term':{ + 'type': 'ext:memcached', + 'url': '127.0.0.1:11211', + 'expire': 300 + } + }) + + lookup = TemplateLookup( + directories=['/path/to/templates'], + module_directory='/path/to/modules', + cache_impl='beaker', + cache_args={ + 'manager':manager + } + ) + +Our templates can then opt to cache data in one of either region, +using the ``cache_region`` argument. Such as using ``short_term`` +at the ``<%page>`` level: + +.. sourcecode:: mako + + <%page cached="True" cache_region="short_term"> + + ## ... + +Or, ``long_term`` at the ``<%block>`` level: + +.. sourcecode:: mako + + <%block name="header" cached="True" cache_region="long_term"> + other text + + +The Beaker backend also works without regions. There are a +variety of arguments that can be passed to the ``cache_args`` +dictionary, which are also allowable in templates via the +``<%page>``, ``<%block>``, +and ``<%def>`` tags specific to those sections. The values +given override those specified at the :class:`.TemplateLookup` +or :class:`.Template` level. + +With the possible exception +of ``cache_timeout``, these arguments are probably better off +staying at the template configuration level. Each argument +specified as ``cache_XYZ`` in a template tag is specified +without the ``cache_`` prefix in the ``cache_args`` dictionary: + +* ``cache_timeout`` - number of seconds in which to invalidate the + cached data. After this timeout, the content is re-generated + on the next call. Available as ``timeout`` in the ``cache_args`` + dictionary. +* ``cache_type`` - type of caching. ``'memory'``, ``'file'``, ``'dbm'``, or + ``'ext:memcached'`` (note that the string ``memcached`` is + also accepted by the dogpile.cache Mako plugin, though not by Beaker itself). + Available as ``type`` in the ``cache_args`` dictionary. +* ``cache_url`` - (only used for ``memcached`` but required) a single + IP address or a semi-colon separated list of IP address of + memcache servers to use. Available as ``url`` in the ``cache_args`` + dictionary. +* ``cache_dir`` - in the case of the ``'file'`` and ``'dbm'`` cache types, + this is the filesystem directory with which to store data + files. If this option is not present, the value of + ``module_directory`` is used (i.e. the directory where compiled + template modules are stored). If neither option is available + an exception is thrown. Available as ``dir`` in the + ``cache_args`` dictionary. + +.. _dogpile.cache_backend: + +Using the dogpile.cache Backend +------------------------------- + +`dogpile.cache`_ is a new replacement for Beaker. It provides +a modernized, slimmed down interface and is generally easier to use +than Beaker. As of this writing it has not yet been released. dogpile.cache +includes its own Mako cache plugin -- see :mod:`dogpile.cache.plugins.mako_cache` in the +dogpile.cache documentation. + +Programmatic Cache Access +========================= + +The :class:`.Template`, as well as any template-derived :class:`.Namespace`, has +an accessor called ``cache`` which returns the :class:`.Cache` object +for that template. This object is a facade on top of the underlying +:class:`.CacheImpl` object, and provides some very rudimental +capabilities, such as the ability to get and put arbitrary +values: + +.. sourcecode:: mako + + <% + local.cache.set("somekey", type="memory", "somevalue") + %> + +Above, the cache associated with the ``local`` namespace is +accessed and a key is placed within a memory cache. + +More commonly, the ``cache`` object is used to invalidate cached +sections programmatically: + +.. sourcecode:: python + + template = lookup.get_template('/sometemplate.html') + + # invalidate the "body" of the template + template.cache.invalidate_body() + + # invalidate an individual def + template.cache.invalidate_def('somedef') + + # invalidate an arbitrary key + template.cache.invalidate('somekey') + +You can access any special method or attribute of the :class:`.CacheImpl` +itself using the :attr:`impl <.Cache.impl>` attribute: + +.. sourcecode:: python + + template.cache.impl.do_something_special() + +Note that using implementation-specific methods will mean you can't +swap in a different kind of :class:`.CacheImpl` implementation at a +later time. + +.. _cache_plugins: + +Cache Plugins +============= + +The mechanism used by caching can be plugged in +using a :class:`.CacheImpl` subclass. This class implements +the rudimental methods Mako needs to implement the caching +API. Mako includes the :class:`.BeakerCacheImpl` class to +provide the default implementation. A :class:`.CacheImpl` class +is acquired by Mako using a ``pkg_resources`` entrypoint, using +the name given as the ``cache_impl`` argument to :class:`.Template` +or :class:`.TemplateLookup`. This entry point can be +installed via the standard `setuptools`/``setup()`` procedure, underneath +the `EntryPoint` group named ``"mako.cache"``. It can also be +installed at runtime via a convenience installer :func:`.register_plugin` +which accomplishes essentially the same task. + +An example plugin that implements a local dictionary cache: + +.. sourcecode:: python + + from mako.cache import Cacheimpl, register_plugin + + class SimpleCacheImpl(CacheImpl): + def __init__(self, cache): + super(SimpleCacheImpl, self).__init__(cache) + self._cache = {} + + def get_or_create(self, key, creation_function, **kw): + if key in self._cache: + return self._cache[key] + else: + self._cache[key] = value = creation_function() + return value + + def set(self, key, value, **kwargs): + self._cache[key] = value + + def get(self, key, **kwargs): + return self._cache.get(key) + + def invalidate(self, key, **kwargs): + self._cache.pop(key, None) + + # optional - register the class locally + register_plugin("simple", __name__, "SimpleCacheImpl") + +Enabling the above plugin in a template would look like: + +.. sourcecode:: python + + t = Template("mytemplate", + file="mytemplate.html", + cache_impl='simple') + +Guidelines for Writing Cache Plugins +------------------------------------ + +* The :class:`.CacheImpl` is created on a per-:class:`.Template` basis. The + class should ensure that only data for the parent :class:`.Template` is + persisted or returned by the cache methods. The actual :class:`.Template` + is available via the ``self.cache.template`` attribute. The ``self.cache.id`` + attribute, which is essentially the unique modulename of the template, is + a good value to use in order to represent a unique namespace of keys specific + to the template. +* Templates only use the :meth:`.CacheImpl.get_or_create()` method + in an implicit fashion. The :meth:`.CacheImpl.set`, + :meth:`.CacheImpl.get`, and :meth:`.CacheImpl.invalidate` methods are + only used in response to direct programmatic access to the corresponding + methods on the :class:`.Cache` object. +* :class:`.CacheImpl` will be accessed in a multithreaded fashion if the + :class:`.Template` itself is used multithreaded. Care should be taken + to ensure caching implementations are threadsafe. +* A library like `Dogpile `_, which + is a minimal locking system derived from Beaker, can be used to help + implement the :meth:`.CacheImpl.get_or_create` method in a threadsafe + way that can maximize effectiveness across multiple threads as well + as processes. :meth:`.CacheImpl.get_or_create` is the + key method used by templates. +* All arguments passed to ``**kw`` come directly from the parameters + inside the ``<%def>``, ``<%block>``, or ``<%page>`` tags directly, + minus the ``"cache_"`` prefix, as strings, with the exception of + the argument ``cache_timeout``, which is passed to the plugin + as the name ``timeout`` with the value converted to an integer. + Arguments present in ``cache_args`` on :class:`.Template` or + :class:`.TemplateLookup` are passed directly, but are superseded + by those present in the most specific template tag. +* The directory where :class:`.Template` places module files can + be acquired using the accessor ``self.cache.template.module_directory``. + This directory can be a good place to throw cache-related work + files, underneath a prefix like ``_my_cache_work`` so that name + conflicts with generated modules don't occur. + +API Reference +============= + +.. autoclass:: mako.cache.Cache + :members: + :show-inheritance: + +.. autoclass:: mako.cache.CacheImpl + :members: + :show-inheritance: + +.. autofunction:: mako.cache.register_plugin + +.. autoclass:: mako.ext.beaker_cache.BeakerCacheImpl + :members: + :show-inheritance: + diff --git a/lib/mako-0.7.2/doc/_sources/defs.txt b/lib/mako-0.7.2/doc/_sources/defs.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/defs.txt @@ -0,0 +1,622 @@ +.. _defs_toplevel: + +=============== +Defs and Blocks +=============== + +``<%def>`` and ``<%block>`` are two tags that both demarcate any block of text +and/or code. They both exist within generated Python as a callable function, +i.e., a Python ``def``. They differ in their scope and calling semantics. +Whereas ``<%def>`` provides a construct that is very much like a named Python +``def``, the ``<%block>`` is more layout oriented. + +Using Defs +========== + +The ``<%def>`` tag requires a ``name`` attribute, where the ``name`` references +a Python function signature: + +.. sourcecode:: mako + + <%def name="hello()"> + hello world + + +To invoke the ``<%def>``, it is normally called as an expression: + +.. sourcecode:: mako + + the def: ${hello()} + +If the ``<%def>`` is not nested inside of another ``<%def>``, +it's known as a **top level def** and can be accessed anywhere in +the template, including above where it was defined. + +All defs, top level or not, have access to the current +contextual namespace in exactly the same way their containing +template does. Suppose the template below is executed with the +variables ``username`` and ``accountdata`` inside the context: + +.. sourcecode:: mako + + Hello there ${username}, how are ya. Lets see what your account says: + + ${account()} + + <%def name="account()"> + Account for ${username}:
+ + % for row in accountdata: + Value: ${row}
+ % endfor + + +The ``username`` and ``accountdata`` variables are present +within the main template body as well as the body of the +``account()`` def. + +Since defs are just Python functions, you can define and pass +arguments to them as well: + +.. sourcecode:: mako + + ${account(accountname='john')} + + <%def name="account(accountname, type='regular')"> + account name: ${accountname}, type: ${type} + + +When you declare an argument signature for your def, they are +required to follow normal Python conventions (i.e., all +arguments are required except keyword arguments with a default +value). This is in contrast to using context-level variables, +which evaluate to ``UNDEFINED`` if you reference a name that +does not exist. + +Calling Defs from Other Files +----------------------------- + +Top level ``<%def>``\ s are **exported** by your template's +module, and can be called from the outside; including from other +templates, as well as normal Python code. Calling a ``<%def>`` +from another template is something like using an ``<%include>`` +-- except you are calling a specific function within the +template, not the whole template. + +The remote ``<%def>`` call is also a little bit like calling +functions from other modules in Python. There is an "import" +step to pull the names from another template into your own +template; then the function or functions are available. + +To import another template, use the ``<%namespace>`` tag: + +.. sourcecode:: mako + + <%namespace name="mystuff" file="mystuff.html"/> + +The above tag adds a local variable ``mystuff`` to the current +scope. + +Then, just call the defs off of ``mystuff``: + +.. sourcecode:: mako + + ${mystuff.somedef(x=5,y=7)} + +The ``<%namespace>`` tag also supports some of the other +semantics of Python's ``import`` statement, including pulling +names into the local variable space, or using ``*`` to represent +all names, using the ``import`` attribute: + +.. sourcecode:: mako + + <%namespace file="mystuff.html" import="foo, bar"/> + +This is just a quick intro to the concept of a **namespace**, +which is a central Mako concept that has its own chapter in +these docs. For more detail and examples, see +:ref:`namespaces_toplevel`. + +Calling Defs Programmatically +----------------------------- + +You can call defs programmatically from any :class:`.Template` object +using the :meth:`~.Template.get_def()` method, which returns a :class:`.DefTemplate` +object. This is a :class:`.Template` subclass which the parent +:class:`.Template` creates, and is usable like any other template: + +.. sourcecode:: python + + from mako.template import Template + + template = Template(""" + <%def name="hi(name)"> + hi ${name}! + + + <%def name="bye(name)"> + bye ${name}! + + """) + + print template.get_def("hi").render(name="ed") + print template.get_def("bye").render(name="ed") + +Defs within Defs +---------------- + +The def model follows regular Python rules for closures. +Declaring ``<%def>`` inside another ``<%def>`` declares it +within the parent's **enclosing scope**: + +.. sourcecode:: mako + + <%def name="mydef()"> + <%def name="subdef()"> + a sub def + + + i'm the def, and the subcomponent is ${subdef()} + + +Just like Python, names that exist outside the inner ``<%def>`` +exist inside it as well: + +.. sourcecode:: mako + + <% + x = 12 + %> + <%def name="outer()"> + <% + y = 15 + %> + <%def name="inner()"> + inner, x is ${x}, y is ${y} + + + outer, x is ${x}, y is ${y} + + +Assigning to a name inside of a def declares that name as local +to the scope of that def (again, like Python itself). This means +the following code will raise an error: + +.. sourcecode:: mako + + <% + x = 10 + %> + <%def name="somedef()"> + ## error ! + somedef, x is ${x} + <% + x = 27 + %> + + +...because the assignment to ``x`` declares ``x`` as local to the +scope of ``somedef``, rendering the "outer" version unreachable +in the expression that tries to render it. + +.. _defs_with_content: + +Calling a Def with Embedded Content and/or Other Defs +----------------------------------------------------- + +A flip-side to def within def is a def call with content. This +is where you call a def, and at the same time declare a block of +content (or multiple blocks) that can be used by the def being +called. The main point of such a call is to create custom, +nestable tags, just like any other template language's +custom-tag creation system -- where the external tag controls the +execution of the nested tags and can communicate state to them. +Only with Mako, you don't have to use any external Python +modules, you can define arbitrarily nestable tags right in your +templates. + +To achieve this, the target def is invoked using the form +``<%namepacename:defname>`` instead of the normal ``${}`` +syntax. This syntax, introduced in Mako 0.2.3, is functionally +equivalent to another tag known as ``%call``, which takes the form +``<%call expr='namespacename.defname(args)'>``. While ``%call`` +is available in all versions of Mako, the newer style is +probably more familiar looking. The ``namespace`` portion of the +call is the name of the **namespace** in which the def is +defined -- in the most simple cases, this can be ``local`` or +``self`` to reference the current template's namespace (the +difference between ``local`` and ``self`` is one of inheritance +-- see :ref:`namespaces_builtin` for details). + +When the target def is invoked, a variable ``caller`` is placed +in its context which contains another namespace containing the +body and other defs defined by the caller. The body itself is +referenced by the method ``body()``. Below, we build a ``%def`` +that operates upon ``caller.body()`` to invoke the body of the +custom tag: + +.. sourcecode:: mako + + <%def name="buildtable()"> + + +
+ ${caller.body()} +
+ + + <%self:buildtable> + I am the table body. + + +This produces the output (whitespace formatted): + +.. sourcecode:: html + + + +
+ I am the table body. +
+ +Using the older ``%call`` syntax looks like: + +.. sourcecode:: mako + + <%def name="buildtable()"> + + +
+ ${caller.body()} +
+ + + <%call expr="buildtable()"> + I am the table body. + + +The ``body()`` can be executed multiple times or not at all. +This means you can use def-call-with-content to build iterators, +conditionals, etc: + +.. sourcecode:: mako + + <%def name="lister(count)"> + % for x in range(count): + ${caller.body()} + % endfor + + + <%self:lister count="${3}"> + hi + + +Produces: + +.. sourcecode:: html + + hi + hi + hi + +Notice above we pass ``3`` as a Python expression, so that it +remains as an integer. + +A custom "conditional" tag: + +.. sourcecode:: mako + + <%def name="conditional(expression)"> + % if expression: + ${caller.body()} + % endif + + + <%self:conditional expression="${4==4}"> + i'm the result + + +Produces: + +.. sourcecode:: html + + i'm the result + +But that's not all. The ``body()`` function also can handle +arguments, which will augment the local namespace of the body +callable. The caller must define the arguments which it expects +to receive from its target def using the ``args`` attribute, +which is a comma-separated list of argument names. Below, our +``<%def>`` calls the ``body()`` of its caller, passing in an +element of data from its argument: + +.. sourcecode:: mako + + <%def name="layoutdata(somedata)"> + + % for item in somedata: + + % for col in item: + + % endfor + + % endfor +
${caller.body(col=col)}
+ + + <%self:layoutdata somedata="${[[1,2,3],[4,5,6],[7,8,9]]}" args="col">\ + Body data: ${col}\ + + +Produces: + +.. sourcecode:: html + + + + + + + + + + + + + + + + + +
Body data: 1Body data: 2Body data: 3
Body data: 4Body data: 5Body data: 6
Body data: 7Body data: 8Body data: 9
+ +You don't have to stick to calling just the ``body()`` function. +The caller can define any number of callables, allowing the +``<%call>`` tag to produce whole layouts: + +.. sourcecode:: mako + + <%def name="layout()"> + ## a layout def +
+
+ ${caller.header()} +
+ + + +
+ ${caller.body()} +
+
+ + + ## calls the layout def + <%self:layout> + <%def name="header()"> + I am the header + + <%def name="sidebar()"> +
    +
  • sidebar 1
  • +
  • sidebar 2
  • +
+ + + this is the body + + +The above layout would produce: + +.. sourcecode:: html + +
+
+ I am the header +
+ + + +
+ this is the body +
+
+ +The number of things you can do with ``<%call>`` and/or the +``<%namespacename:defname>`` calling syntax is enormous. You can +create form widget libraries, such as an enclosing ``
`` +tag and nested HTML input elements, or portable wrapping schemes +using ``
`` or other elements. You can create tags that +interpret rows of data, such as from a database, providing the +individual columns of each row to a ``body()`` callable which +lays out the row any way it wants. Basically anything you'd do +with a "custom tag" or tag library in some other system, Mako +provides via ``<%def>`` tags and plain Python callables which are +invoked via ``<%namespacename:defname>`` or ``<%call>``. + +.. _blocks: + +Using Blocks +============ + +The ``<%block>`` tag introduces some new twists on the +``<%def>`` tag which make it more closely tailored towards layout. + +.. versionadded:: 0.4.1 + +An example of a block: + +.. sourcecode:: mako + + + + <%block> + this is a block. + + + + +In the above example, we define a simple block. The block renders its content in the place +that it's defined. Since the block is called for us, it doesn't need a name and the above +is referred to as an **anonymous block**. So the output of the above template will be: + +.. sourcecode:: html + + + + this is a block. + + + +So in fact the above block has absolutely no effect. Its usefulness comes when we start +using modifiers. Such as, we can apply a filter to our block: + +.. sourcecode:: mako + + + + <%block filter="h"> + this is some escaped html. + + + + +or perhaps a caching directive: + +.. sourcecode:: mako + + + + <%block cached="True" cache_timeout="60"> + This content will be cached for 60 seconds. + + + + +Blocks also work in iterations, conditionals, just like defs: + +.. sourcecode:: mako + + % if some_condition: + <%block>condition is met + % endif + +While the block renders at the point it is defined in the template, +the underlying function is present in the generated Python code only +once, so there's no issue with placing a block inside of a loop or +similar. Anonymous blocks are defined as closures in the local +rendering body, so have access to local variable scope: + +.. sourcecode:: mako + + % for i in range(1, 4): + <%block>i is ${i} + % endfor + +Using Named Blocks +------------------ + +Possibly the more important area where blocks are useful is when we +do actually give them names. Named blocks are tailored to behave +somewhat closely to Jinja2's block tag, in that they define an area +of a layout which can be overridden by an inheriting template. In +sharp contrast to the ``<%def>`` tag, the name given to a block is +global for the entire template regardless of how deeply it's nested: + +.. sourcecode:: mako + + + <%block name="header"> + + + <%block name="title">Title</%block> + + + + + ${next.body()} + + + +The above example has two named blocks "``header``" and "``title``", both of which can be referred to +by an inheriting template. A detailed walkthrough of this usage can be found at :ref:`inheritance_toplevel`. + +Note above that named blocks don't have any argument declaration the way defs do. They still implement themselves +as Python functions, however, so they can be invoked additional times beyond their initial definition: + +.. sourcecode:: mako + +
+ <%block name="pagecontrol"> + previous page | + next page + + + + ## some content +
+ + ${pagecontrol()} +
+ +The content referenced by ``pagecontrol`` above will be rendered both above and below the ```` tags. + +To keep things sane, named blocks have restrictions that defs do not: + +* The ``<%block>`` declaration cannot have any argument signature. +* The name of a ``<%block>`` can only be defined once in a template -- an error is raised if two blocks of the same + name occur anywhere in a single template, regardless of nesting. A similar error is raised if a top level def + shares the same name as that of a block. +* A named ``<%block>`` cannot be defined within a ``<%def>``, or inside the body of a "call", i.e. + ``<%call>`` or ``<%namespacename:defname>`` tag. Anonymous blocks can, however. + +Using Page Arguments in Named Blocks +------------------------------------ + +A named block is very much like a top level def. It has a similar +restriction to these types of defs in that arguments passed to the +template via the ``<%page>`` tag aren't automatically available. +Using arguments with the ``<%page>`` tag is described in the section +:ref:`namespaces_body`, and refers to scenarios such as when the +``body()`` method of a template is called from an inherited template passing +arguments, or the template is invoked from an ``<%include>`` tag +with arguments. To allow a named block to share the same arguments +passed to the page, the ``args`` attribute can be used: + +.. sourcecode:: mako + + <%page args="post"/> + + + + + <%block name="post_prose" args="post"> + ${post.content} + + + +Where above, if the template is called via a directive like +``<%include file="post.mako" args="post=post" />``, the ``post`` +variable is available both in the main body as well as the +``post_prose`` block. + +Similarly, the ``**pageargs`` variable is present, in named blocks only, +for those arguments not explicit in the ``<%page>`` tag: + +.. sourcecode:: mako + + <%block name="post_prose"> + ${pageargs['post'].content} + + +The ``args`` attribute is only allowed with named blocks. With +anonymous blocks, the Python function is always rendered in the same +scope as the call itself, so anything available directly outside the +anonymous block is available inside as well. diff --git a/lib/mako-0.7.2/doc/_sources/filtering.txt b/lib/mako-0.7.2/doc/_sources/filtering.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/filtering.txt @@ -0,0 +1,344 @@ +.. _filtering_toplevel: + +======================= +Filtering and Buffering +======================= + +Expression Filtering +==================== + +As described in the chapter :ref:`syntax_toplevel`, the "``|``" operator can be +applied to a "``${}``" expression to apply escape filters to the +output: + +.. sourcecode:: mako + + ${"this is some text" | u} + +The above expression applies URL escaping to the expression, and +produces ``this+is+some+text``. + +The built-in escape flags are: + +* ``u`` : URL escaping, provided by + ``urllib.quote_plus(string.encode('utf-8'))`` +* ``h`` : HTML escaping, provided by + ``markupsafe.escape(string)`` + + .. versionadded:: 0.3.4 + Prior versions use ``cgi.escape(string, True)``. + +* ``x`` : XML escaping +* ``trim`` : whitespace trimming, provided by ``string.strip()`` +* ``entity`` : produces HTML entity references for applicable + strings, derived from ``htmlentitydefs`` +* ``unicode`` (``str`` on Python 3): produces a Python unicode + string (this function is applied by default) +* ``decode.``: decode input into a Python + unicode with the specified encoding +* ``n`` : disable all default filtering; only filters specified + in the local expression tag will be applied. + +To apply more than one filter, separate them by a comma: + +.. sourcecode:: mako + + ${" some value " | h,trim} + +The above produces ``<tag>some value</tag>``, with +no leading or trailing whitespace. The HTML escaping function is +applied first, the "trim" function second. + +Naturally, you can make your own filters too. A filter is just a +Python function that accepts a single string argument, and +returns the filtered result. The expressions after the ``|`` +operator draw upon the local namespace of the template in which +they appear, meaning you can define escaping functions locally: + +.. sourcecode:: mako + + <%! + def myescape(text): + return "" + text + "" + %> + + Here's some tagged text: ${"text" | myescape} + +Or from any Python module: + +.. sourcecode:: mako + + <%! + import myfilters + %> + + Here's some tagged text: ${"text" | myfilters.tagfilter} + +A page can apply a default set of filters to all expression tags +using the ``expression_filter`` argument to the ``%page`` tag: + +.. sourcecode:: mako + + <%page expression_filter="h"/> + + Escaped text: ${"some html"} + +Result: + +.. sourcecode:: html + + Escaped text: <html>some html</html> + +.. _filtering_default_filters: + +The ``default_filters`` Argument +-------------------------------- + +In addition to the ``expression_filter`` argument, the +``default_filters`` argument to both :class:`.Template` and +:class:`.TemplateLookup` can specify filtering for all expression tags +at the programmatic level. This array-based argument, when given +its default argument of ``None``, will be internally set to +``["unicode"]`` (or ``["str"]`` on Python 3), except when +``disable_unicode=True`` is set in which case it defaults to +``["str"]``: + +.. sourcecode:: python + + t = TemplateLookup(directories=['/tmp'], default_filters=['unicode']) + +To replace the usual ``unicode``/``str`` function with a +specific encoding, the ``decode`` filter can be substituted: + +.. sourcecode:: python + + t = TemplateLookup(directories=['/tmp'], default_filters=['decode.utf8']) + +To disable ``default_filters`` entirely, set it to an empty +list: + +.. sourcecode:: python + + t = TemplateLookup(directories=['/tmp'], default_filters=[]) + +Any string name can be added to ``default_filters`` where it +will be added to all expressions as a filter. The filters are +applied from left to right, meaning the leftmost filter is +applied first. + +.. sourcecode:: python + + t = Template(templatetext, default_filters=['unicode', 'myfilter']) + +To ease the usage of ``default_filters`` with custom filters, +you can also add imports (or other code) to all templates using +the ``imports`` argument: + +.. sourcecode:: python + + t = TemplateLookup(directories=['/tmp'], + default_filters=['unicode', 'myfilter'], + imports=['from mypackage import myfilter']) + +The above will generate templates something like this: + +.. sourcecode:: python + + # .... + from mypackage import myfilter + + def render_body(context): + context.write(myfilter(unicode("some text"))) + +Turning off Filtering with the ``n`` Filter +------------------------------------------- + +In all cases the special ``n`` filter, used locally within an +expression, will **disable** all filters declared in the +``<%page>`` tag as well as in ``default_filters``. Such as: + +.. sourcecode:: mako + + ${'myexpression' | n} + +will render ``myexpression`` with no filtering of any kind, and: + +.. sourcecode:: mako + + ${'myexpression' | n,trim} + +will render ``myexpression`` using the ``trim`` filter only. + +Filtering Defs and Blocks +========================= + +The ``%def`` and ``%block`` tags have an argument called ``filter`` which will apply the +given list of filter functions to the output of the ``%def``: + +.. sourcecode:: mako + + <%def name="foo()" filter="h, trim"> + this is bold + + +When the ``filter`` attribute is applied to a def as above, the def +is automatically **buffered** as well. This is described next. + +Buffering +========= + +One of Mako's central design goals is speed. To this end, all of +the textual content within a template and its various callables +is by default piped directly to the single buffer that is stored +within the :class:`.Context` object. While this normally is easy to +miss, it has certain side effects. The main one is that when you +call a def using the normal expression syntax, i.e. +``${somedef()}``, it may appear that the return value of the +function is the content it produced, which is then delivered to +your template just like any other expression substitution, +except that normally, this is not the case; the return value of +``${somedef()}`` is simply the empty string ``''``. By the time +you receive this empty string, the output of ``somedef()`` has +been sent to the underlying buffer. + +You may not want this effect, if for example you are doing +something like this: + +.. sourcecode:: mako + + ${" results " + somedef() + " more results "} + +If the ``somedef()`` function produced the content "``somedef's +results``", the above template would produce this output: + +.. sourcecode:: html + + somedef's results results more results + +This is because ``somedef()`` fully executes before the +expression returns the results of its concatenation; the +concatenation in turn receives just the empty string as its +middle expression. + +Mako provides two ways to work around this. One is by applying +buffering to the ``%def`` itself: + +.. sourcecode:: mako + + <%def name="somedef()" buffered="True"> + somedef's results + + +The above definition will generate code similar to this: + +.. sourcecode:: python + + def somedef(): + context.push_buffer() + try: + context.write("somedef's results") + finally: + buf = context.pop_buffer() + return buf.getvalue() + +So that the content of ``somedef()`` is sent to a second buffer, +which is then popped off the stack and its value returned. The +speed hit inherent in buffering the output of a def is also +apparent. + +Note that the ``filter`` argument on ``%def`` also causes the def to +be buffered. This is so that the final content of the ``%def`` can +be delivered to the escaping function in one batch, which +reduces method calls and also produces more deterministic +behavior for the filtering function itself, which can possibly +be useful for a filtering function that wishes to apply a +transformation to the text as a whole. + +The other way to buffer the output of a def or any Mako callable +is by using the built-in ``capture`` function. This function +performs an operation similar to the above buffering operation +except it is specified by the caller. + +.. sourcecode:: mako + + ${" results " + capture(somedef) + " more results "} + +Note that the first argument to the ``capture`` function is +**the function itself**, not the result of calling it. This is +because the ``capture`` function takes over the job of actually +calling the target function, after setting up a buffered +environment. To send arguments to the function, just send them +to ``capture`` instead: + +.. sourcecode:: mako + + ${capture(somedef, 17, 'hi', use_paging=True)} + +The above call is equivalent to the unbuffered call: + +.. sourcecode:: mako + + ${somedef(17, 'hi', use_paging=True)} + +Decorating +========== + +.. versionadded:: 0.2.5 + +Somewhat like a filter for a ``%def`` but more flexible, the ``decorator`` +argument to ``%def`` allows the creation of a function that will +work in a similar manner to a Python decorator. The function can +control whether or not the function executes. The original +intent of this function is to allow the creation of custom cache +logic, but there may be other uses as well. + +``decorator`` is intended to be used with a regular Python +function, such as one defined in a library module. Here we'll +illustrate the python function defined in the template for +simplicities' sake: + +.. sourcecode:: mako + + <%! + def bar(fn): + def decorate(context, *args, **kw): + context.write("BAR") + fn(*args, **kw) + context.write("BAR") + return '' + return decorate + %> + + <%def name="foo()" decorator="bar"> + this is foo + + + ${foo()} + +The above template will return, with more whitespace than this, +``"BAR this is foo BAR"``. The function is the render callable +itself (or possibly a wrapper around it), and by default will +write to the context. To capture its output, use the :func:`.capture` +callable in the ``mako.runtime`` module (available in templates +as just ``runtime``): + +.. sourcecode:: mako + + <%! + def bar(fn): + def decorate(context, *args, **kw): + return "BAR" + runtime.capture(context, fn, *args, **kw) + "BAR" + return decorate + %> + + <%def name="foo()" decorator="bar"> + this is foo + + + ${foo()} + +The decorator can be used with top-level defs as well as nested +defs, and blocks too. Note that when calling a top-level def from the +:class:`.Template` API, i.e. ``template.get_def('somedef').render()``, +the decorator has to write the output to the ``context``, i.e. +as in the first example. The return value gets discarded. diff --git a/lib/mako-0.7.2/doc/_sources/index.txt b/lib/mako-0.7.2/doc/_sources/index.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/index.txt @@ -0,0 +1,22 @@ +Table of Contents +================= + +.. toctree:: + :maxdepth: 2 + + usage + syntax + defs + runtime + namespaces + inheritance + filtering + unicode + caching + +Indices and Tables +------------------ + +* :ref:`genindex` +* :ref:`search` + diff --git a/lib/mako-0.7.2/doc/_sources/inheritance.txt b/lib/mako-0.7.2/doc/_sources/inheritance.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/inheritance.txt @@ -0,0 +1,534 @@ +.. _inheritance_toplevel: + +=========== +Inheritance +=========== + +.. note:: Most of the inheritance examples here take advantage of a feature that's + new in Mako as of version 0.4.1 called the "block". This tag is very similar to + the "def" tag but is more streamlined for usage with inheritance. Note that + all of the examples here which use blocks can also use defs instead. Contrasting + usages will be illustrated. + +Using template inheritance, two or more templates can organize +themselves into an **inheritance chain**, where content and +functions from all involved templates can be intermixed. The +general paradigm of template inheritance is this: if a template +``A`` inherits from template ``B``, then template ``A`` agrees +to send the executional control to template ``B`` at runtime +(``A`` is called the **inheriting** template). Template ``B``, +the **inherited** template, then makes decisions as to what +resources from ``A`` shall be executed. + +In practice, it looks like this. Here's a hypothetical inheriting +template, ``index.html``: + +.. sourcecode:: mako + + ## index.html + <%inherit file="base.html"/> + + <%block name="header"> + this is some header content + + + this is the body content. + +And ``base.html``, the inherited template: + +.. sourcecode:: mako + + ## base.html + + +
+ <%block name="header"/> +
+ + ${self.body()} + + + + + +Here is a breakdown of the execution: + +#. When ``index.html`` is rendered, control immediately passes to + ``base.html``. +#. ``base.html`` then renders the top part of an HTML document, + then invokes the ``<%block name="header">`` block. It invokes the + underlying ``header()`` function off of a built-in namespace + called ``self`` (this namespace was first introduced in the + :doc:`Namespaces chapter ` in :ref:`namespace_self`). Since + ``index.html`` is the topmost template and also defines a block + called ``header``, it's this ``header`` block that ultimately gets + executed -- instead of the one that's present in ``base.html``. +#. Control comes back to ``base.html``. Some more HTML is + rendered. +#. ``base.html`` executes ``self.body()``. The ``body()`` + function on all template-based namespaces refers to the main + body of the template, therefore the main body of + ``index.html`` is rendered. +#. When ``<%block name="header">`` is encountered in ``index.html`` + during the ``self.body()`` call, a conditional is checked -- does the + current inherited template, i.e. ``base.html``, also define this block? If yes, + the ``<%block>`` is **not** executed here -- the inheritance + mechanism knows that the parent template is responsible for rendering + this block (and in fact it already has). In other words a block + only renders in its *basemost scope*. +#. Control comes back to ``base.html``. More HTML is rendered, + then the ``<%block name="footer">`` expression is invoked. +#. The ``footer`` block is only defined in ``base.html``, so being + the topmost definition of ``footer``, it's the one that + executes. If ``index.html`` also specified ``footer``, then + its version would **override** that of the base. +#. ``base.html`` finishes up rendering its HTML and the template + is complete, producing: + + .. sourcecode:: html + + + +
+ this is some header content +
+ + this is the body content. + + + + + +...and that is template inheritance in a nutshell. The main idea +is that the methods that you call upon ``self`` always +correspond to the topmost definition of that method. Very much +the way ``self`` works in a Python class, even though Mako is +not actually using Python class inheritance to implement this +functionality. (Mako doesn't take the "inheritance" metaphor too +seriously; while useful to setup some commonly recognized +semantics, a textual template is not very much like an +object-oriented class construct in practice). + +Nesting Blocks +============== + +The named blocks defined in an inherited template can also be nested within +other blocks. The name given to each block is globally accessible via any inheriting +template. We can add a new block ``title`` to our ``header`` block: + +.. sourcecode:: mako + + ## base.html + + +
+ <%block name="header"> +

+ <%block name="title"/> +

+ +
+ + ${self.body()} + + + + + +The inheriting template can name either or both of ``header`` and ``title``, separately +or nested themselves: + +.. sourcecode:: mako + + ## index.html + <%inherit file="base.html"/> + + <%block name="header"> + this is some header content + ${parent.header()} + + + <%block name="title"> + this is the title + + + this is the body content. + +Note when we overrode ``header``, we added an extra call ``${parent.header()}`` in order to invoke +the parent's ``header`` block in addition to our own. That's described in more detail below, +in :ref:`parent_namespace`. + +Rendering a Named Block Multiple Times +====================================== + +Recall from the section :ref:`blocks` that a named block is just like a ``<%def>``, +with some different usage rules. We can call one of our named sections distinctly, for example +a section that is used more than once, such as the title of a page: + +.. sourcecode:: mako + + + + ${self.title()} + + + <%block name="header"> +

<%block name="title"/>

+ + ${self.body()} + + + +Where above an inheriting template can define ``<%block name="title">`` just once, and it will be +used in the base template both in the ```` section as well as the ``<h2>``. + +But what about Defs? +==================== + +The previous example used the ``<%block>`` tag to produce areas of content +to be overridden. Before Mako 0.4.1, there wasn't any such tag -- instead +there was only the ``<%def>`` tag. As it turns out, named blocks and defs are +largely interchangeable. The def simply doesn't call itself automatically, +and has more open-ended naming and scoping rules that are more flexible and similar +to Python itself, but less suited towards layout. The first example from +this chapter using defs would look like: + +.. sourcecode:: mako + + ## index.html + <%inherit file="base.html"/> + + <%def name="header()"> + this is some header content + </%def> + + this is the body content. + +And ``base.html``, the inherited template: + +.. sourcecode:: mako + + ## base.html + <html> + <body> + <div class="header"> + ${self.header()} + </div> + + ${self.body()} + + <div class="footer"> + ${self.footer()} + </div> + </body> + </html> + + <%def name="header()"/> + <%def name="footer()"> + this is the footer + </%def> + +Above, we illustrate that defs differ from blocks in that their definition +and invocation are defined in two separate places, instead of at once. You can *almost* do exactly what a +block does if you put the two together: + +.. sourcecode:: mako + + <div class="header"> + <%def name="header()"></%def>${self.header()} + </div> + +The ``<%block>`` is obviously more streamlined than the ``<%def>`` for this kind +of usage. In addition, +the above "inline" approach with ``<%def>`` does not work with nesting: + +.. sourcecode:: mako + + <head> + <%def name="header()"> + <title> + ## this won't work ! + <%def name="title()">default title</%def>${self.title()} + + ${self.header()} + + +Where above, the ``title()`` def, because it's a def within a def, is not part of the +template's exported namespace and will not be part of ``self``. If the inherited template +did define its own ``title`` def at the top level, it would be called, but the "default title" +above is not present at all on ``self`` no matter what. For this to work as expected +you'd instead need to say: + +.. sourcecode:: mako + + + <%def name="header()"> + + ${self.title()} + + ${self.header()} + + <%def name="title()"/> + + +That is, ``title`` is defined outside of any other defs so that it is in the ``self`` namespace. +It works, but the definition needs to be potentially far away from the point of render. + +A named block is always placed in the ``self`` namespace, regardless of nesting, +so this restriction is lifted: + +.. sourcecode:: mako + + ## base.html + + <%block name="header"> + + <%block name="title"/> + + + + +The above template defines ``title`` inside of ``header``, and an inheriting template can define +one or both in **any** configuration, nested inside each other or not, in order for them to be used: + +.. sourcecode:: mako + + ## index.html + <%inherit file="base.html"/> + <%block name="title"> + the title + + <%block name="header"> + the header + + +So while the ``<%block>`` tag lifts the restriction of nested blocks not being available externally, +in order to achieve this it *adds* the restriction that all block names in a single template need +to be globally unique within the template, and additionally that a ``<%block>`` can't be defined +inside of a ``<%def>``. It's a more restricted tag suited towards a more specific use case than ``<%def>``. + +Using the ``next`` Namespace to Produce Content Wrapping +======================================================== + +Sometimes you have an inheritance chain that spans more than two +templates. Or maybe you don't, but you'd like to build your +system such that extra inherited templates can be inserted in +the middle of a chain where they would be smoothly integrated. +If each template wants to define its layout just within its main +body, you can't just call ``self.body()`` to get at the +inheriting template's body, since that is only the topmost body. +To get at the body of the *next* template, you call upon the +namespace ``next``, which is the namespace of the template +**immediately following** the current template. + +Lets change the line in ``base.html`` which calls upon +``self.body()`` to instead call upon ``next.body()``: + +.. sourcecode:: mako + + ## base.html + + +
+ <%block name="header"/> +
+ + ${next.body()} + + + + + + +Lets also add an intermediate template called ``layout.html``, +which inherits from ``base.html``: + +.. sourcecode:: mako + + ## layout.html + <%inherit file="base.html"/> +
    + <%block name="toolbar"> +
  • selection 1
  • +
  • selection 2
  • +
  • selection 3
  • + +
+
+ ${next.body()} +
+ +And finally change ``index.html`` to inherit from +``layout.html`` instead: + +.. sourcecode:: mako + + ## index.html + <%inherit file="layout.html"/> + + ## .. rest of template + +In this setup, each call to ``next.body()`` will render the body +of the next template in the inheritance chain (which can be +written as ``base.html -> layout.html -> index.html``). Control +is still first passed to the bottommost template ``base.html``, +and ``self`` still references the topmost definition of any +particular def. + +The output we get would be: + +.. sourcecode:: html + + + +
+ this is some header content +
+ +
    +
  • selection 1
  • +
  • selection 2
  • +
  • selection 3
  • +
+ +
+ this is the body content. +
+ + + + + +So above, we have the ````, ```` and +``header``/``footer`` layout of ``base.html``, we have the +``
    `` and ``mainlayout`` section of ``layout.html``, and the +main body of ``index.html`` as well as its overridden ``header`` +def. The ``layout.html`` template is inserted into the middle of +the chain without ``base.html`` having to change anything. +Without the ``next`` namespace, only the main body of +``index.html`` could be used; there would be no way to call +``layout.html``'s body content. + +.. _parent_namespace: + +Using the ``parent`` Namespace to Augment Defs +============================================== + +Lets now look at the other inheritance-specific namespace, the +opposite of ``next`` called ``parent``. ``parent`` is the +namespace of the template **immediately preceding** the current +template. What's useful about this namespace is that +defs or blocks can call upon their overridden versions. +This is not as hard as it sounds and +is very much like using the ``super`` keyword in Python. Lets +modify ``index.html`` to augment the list of selections provided +by the ``toolbar`` function in ``layout.html``: + +.. sourcecode:: mako + + ## index.html + <%inherit file="layout.html"/> + + <%block name="header"> + this is some header content + + + <%block name="toolbar"> + ## call the parent's toolbar first + ${parent.toolbar()} +
  • selection 4
  • +
  • selection 5
  • + + + this is the body content. + +Above, we implemented a ``toolbar()`` function, which is meant +to override the definition of ``toolbar`` within the inherited +template ``layout.html``. However, since we want the content +from that of ``layout.html`` as well, we call it via the +``parent`` namespace whenever we want it's content, in this case +before we add our own selections. So the output for the whole +thing is now: + +.. sourcecode:: html + + + +
    + this is some header content +
    + +
      +
    • selection 1
    • +
    • selection 2
    • +
    • selection 3
    • +
    • selection 4
    • +
    • selection 5
    • +
    + +
    + this is the body content. +
    + + + + + +and you're now a template inheritance ninja! + +Inheritable Attributes +====================== + +The :attr:`attr <.Namespace.attr>` accessor of the :class:`.Namespace` object +allows access to module level variables declared in a template. By accessing +``self.attr``, you can access regular attributes from the +inheritance chain as declared in ``<%! %>`` sections. Such as: + +.. sourcecode:: mako + + <%! + class_ = "grey" + %> + +
    + ${self.body()} +
    + +If an inheriting template overrides ``class_`` to be +``"white"``, as in: + +.. sourcecode:: mako + + <%! + class_ = "white" + %> + <%inherit file="parent.html"/> + + This is the body + +you'll get output like: + +.. sourcecode:: html + +
    + This is the body +
    + diff --git a/lib/mako-0.7.2/doc/_sources/namespaces.txt b/lib/mako-0.7.2/doc/_sources/namespaces.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/namespaces.txt @@ -0,0 +1,349 @@ +.. _namespaces_toplevel: + +========== +Namespaces +========== + +Namespaces are used to organize groups of defs into +categories, and also to "import" defs from other files. + +If the file ``components.html`` defines these two defs: + +.. sourcecode:: mako + + ## components.html + <%def name="comp1()"> + this is comp1 + + + <%def name="comp2(x)"> + this is comp2, x is ${x} + + +you can make another file, for example ``index.html``, that +pulls those two defs into a namespace called ``comp``: + +.. sourcecode:: mako + + ## index.html + <%namespace name="comp" file="components.html"/> + + Here's comp1: ${comp.comp1()} + Here's comp2: ${comp.comp2(x=5)} + +The ``comp`` variable above is an instance of +:class:`.Namespace`, a **proxy object** which delivers +method calls to the underlying template callable using the +current context. + +``<%namespace>`` also provides an ``import`` attribute which can +be used to pull the names into the local namespace, removing the +need to call it via the "``.``" operator. When ``import`` is used, the +``name`` attribute is optional. + +.. sourcecode:: mako + + <%namespace file="components.html" import="comp1, comp2"/> + + Heres comp1: ${comp1()} + Heres comp2: ${comp2(x=5)} + +``import`` also supports the "``*``" operator: + +.. sourcecode:: mako + + <%namespace file="components.html" import="*"/> + + Heres comp1: ${comp1()} + Heres comp2: ${comp2(x=5)} + +The names imported by the ``import`` attribute take precedence +over any names that exist within the current context. + +.. note:: In current versions of Mako, usage of ``import='*'`` is + known to decrease performance of the template. This will be + fixed in a future release. + +The ``file`` argument allows expressions -- if looking for +context variables, the ``context`` must be named explicitly: + +.. sourcecode:: mako + + <%namespace name="dyn" file="${context['namespace_name']}"/> + +Ways to Call Namespaces +======================= + +There are essentially four ways to call a function from a +namespace. + +The "expression" format, as described previously. Namespaces are +just Python objects with functions on them, and can be used in +expressions like any other function: + +.. sourcecode:: mako + + ${mynamespace.somefunction('some arg1', 'some arg2', arg3='some arg3', arg4='some arg4')} + +Synonymous with the "expression" format is the "custom tag" +format, when a "closed" tag is used. This format, introduced in +Mako 0.2.3, allows the usage of a "custom" Mako tag, with the +function arguments passed in using named attributes: + +.. sourcecode:: mako + + <%mynamespace:somefunction arg1="some arg1" arg2="some arg2" arg3="some arg3" arg4="some arg4"/> + +When using tags, the values of the arguments are taken as +literal strings by default. To embed Python expressions as +arguments, use the embedded expression format: + +.. sourcecode:: mako + + <%mynamespace:somefunction arg1="${someobject.format()}" arg2="${somedef(5, 12)}"/> + +The "custom tag" format is intended mainly for namespace +functions which recognize body content, which in Mako is known +as a "def with embedded content": + +.. sourcecode:: mako + + <%mynamespace:somefunction arg1="some argument" args="x, y"> + Some record: ${x}, ${y} + + +The "classic" way to call defs with embedded content is the ``<%call>`` tag: + +.. sourcecode:: mako + + <%call expr="mynamespace.somefunction(arg1='some argument')" args="x, y"> + Some record: ${x}, ${y} + + +For information on how to construct defs that embed content from +the caller, see :ref:`defs_with_content`. + +.. _namespaces_python_modules: + +Namespaces from Regular Python Modules +====================================== + +Namespaces can also import regular Python functions from +modules. These callables need to take at least one argument, +``context``, an instance of :class:`.Context`. A module file +``some/module.py`` might contain the callable: + +.. sourcecode:: python + + def my_tag(context): + context.write("hello world") + return '' + +A template can use this module via: + +.. sourcecode:: mako + + <%namespace name="hw" module="some.module"/> + + ${hw.my_tag()} + +Note that the ``context`` argument is not needed in the call; +the :class:`.Namespace` tag creates a locally-scoped callable which +takes care of it. The ``return ''`` is so that the def does not +dump a ``None`` into the output stream -- the return value of any +def is rendered after the def completes, in addition to whatever +was passed to :meth:`.Context.write` within its body. + +If your def is to be called in an "embedded content" context, +that is as described in :ref:`defs_with_content`, you should use +the :func:`.supports_caller` decorator, which will ensure that Mako +will ensure the correct "caller" variable is available when your +def is called, supporting embedded content: + +.. sourcecode:: python + + from mako.runtime import supports_caller + + @supports_caller + def my_tag(context): + context.write("
    ") + context['caller'].body() + context.write("
    ") + return '' + +Capturing of output is available as well, using the +outside-of-templates version of the :func:`.capture` function, +which accepts the "context" as its first argument: + +.. sourcecode:: python + + from mako.runtime import supports_caller, capture + + @supports_caller + def my_tag(context): + return "
    %s
    " % \ + capture(context, context['caller'].body, x="foo", y="bar") + +Declaring Defs in Namespaces +============================ + +The ``<%namespace>`` tag supports the definition of ``<%def>``\ s +directly inside the tag. These defs become part of the namespace +like any other function, and will override the definitions +pulled in from a remote template or module: + +.. sourcecode:: mako + + ## define a namespace + <%namespace name="stuff"> + <%def name="comp1()"> + comp1 + + + + ## then call it + ${stuff.comp1()} + +.. _namespaces_body: + +The ``body()`` Method +===================== + +Every namespace that is generated from a template contains a +method called ``body()``. This method corresponds to the main +body of the template, and plays its most important roles when +using inheritance relationships as well as +def-calls-with-content. + +Since the ``body()`` method is available from a namespace just +like all the other defs defined in a template, what happens if +you send arguments to it? By default, the ``body()`` method +accepts no positional arguments, and for usefulness in +inheritance scenarios will by default dump all keyword arguments +into a dictionary called ``pageargs``. But if you actually want +to get at the keyword arguments, Mako recommends you define your +own argument signature explicitly. You do this via using the +``<%page>`` tag: + +.. sourcecode:: mako + + <%page args="x, y, someval=8, scope='foo', **kwargs"/> + +A template which defines the above signature requires that the +variables ``x`` and ``y`` are defined, defines default values +for ``someval`` and ``scope``, and sets up ``**kwargs`` to +receive all other keyword arguments. If ``**kwargs`` or similar +is not present, the argument ``**pageargs`` gets tacked on by +Mako. When the template is called as a top-level template (i.e. +via :meth:`~.Template.render`) or via the ``<%include>`` tag, the +values for these arguments will be pulled from the ``Context``. +In all other cases, i.e. via calling the ``body()`` method, the +arguments are taken as ordinary arguments from the method call. +So above, the body might be called as: + +.. sourcecode:: mako + + ${self.body(5, y=10, someval=15, delta=7)} + +The :class:`.Context` object also supplies a :attr:`~.Context.kwargs` accessor, for +cases when you'd like to pass along whatever is in the context to +a ``body()`` callable: + +.. sourcecode:: mako + + ${next.body(**context.kwargs)} + +The usefulness of calls like the above become more apparent when +one works with inheriting templates. For more information on +this, as well as the meanings of the names ``self`` and +``next``, see :ref:`inheritance_toplevel`. + +.. _namespaces_builtin: + +Built-in Namespaces +=================== + +The namespace is so great that Mako gives your template one (or +two) for free. The names of these namespaces are ``local`` and +``self``. Other built-in namespaces include ``parent`` and +``next``, which are optional and are described in +:ref:`inheritance_toplevel`. + +.. _namespace_local: + +``local`` +--------- + +The ``local`` namespace is basically the namespace for the +currently executing template. This means that all of the top +level defs defined in your template, as well as your template's +``body()`` function, are also available off of the ``local`` +namespace. + +The ``local`` namespace is also where properties like ``uri``, +``filename``, and ``module`` and the ``get_namespace`` method +can be particularly useful. + +.. _namespace_self: + +``self`` +-------- + +The ``self`` namespace, in the case of a template that does not +use inheritance, is synonymous with ``local``. If inheritance is +used, then ``self`` references the topmost template in the +inheritance chain, where it is most useful for providing the +ultimate form of various "method" calls which may have been +overridden at various points in an inheritance chain. See +:ref:`inheritance_toplevel`. + +Inheritable Namespaces +====================== + +The ``<%namespace>`` tag includes an optional attribute +``inheritable="True"``, which will cause the namespace to be +attached to the ``self`` namespace. Since ``self`` is globally +available throughout an inheritance chain (described in the next +section), all the templates in an inheritance chain can get at +the namespace imported in a super-template via ``self``. + +.. sourcecode:: mako + + ## base.html + <%namespace name="foo" file="foo.html" inheritable="True"/> + + ${next.body()} + + ## somefile.html + <%inherit file="base.html"/> + + ${self.foo.bar()} + +This allows a super-template to load a whole bunch of namespaces +that its inheriting templates can get to, without them having to +explicitly load those namespaces themselves. + +The ``import="*"`` part of the ``<%namespace>`` tag doesn't yet +interact with the ``inheritable`` flag, so currently you have to +use the explicit namespace name off of ``self``, followed by the +desired function name. But more on this in a future release. + +API Reference +============= + +.. autoclass:: mako.runtime.Namespace + :show-inheritance: + :members: + +.. autoclass:: mako.runtime.TemplateNamespace + :show-inheritance: + :members: + +.. autoclass:: mako.runtime.ModuleNamespace + :show-inheritance: + :members: + +.. autofunction:: mako.runtime.supports_caller + +.. autofunction:: mako.runtime.capture + diff --git a/lib/mako-0.7.2/doc/_sources/runtime.txt b/lib/mako-0.7.2/doc/_sources/runtime.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/runtime.txt @@ -0,0 +1,448 @@ +.. _runtime_toplevel: + +============================ +The Mako Runtime Environment +============================ + +This section describes a little bit about the objects and +built-in functions that are available in templates. + +.. _context: + +Context +======= + +The :class:`.Context` is the central object that is created when +a template is first executed, and is responsible for handling +all communication with the outside world. Within the template +environment, it is available via the :ref:`reserved name ` +``context``. The :class:`.Context` includes two +major components, one of which is the output buffer, which is a +file-like object such as Python's ``StringIO`` or similar, and +the other a dictionary of variables that can be freely +referenced within a template; this dictionary is a combination +of the arguments sent to the :meth:`~.Template.render` function and +some built-in variables provided by Mako's runtime environment. + +The Buffer +---------- + +The buffer is stored within the :class:`.Context`, and writing +to it is achieved by calling the :meth:`~.Context.write` method +-- in a template this looks like ``context.write('some string')``. +You usually don't need to care about this, as all text within a template, as +well as all expressions provided by ``${}``, automatically send +everything to this method. The cases you might want to be aware +of its existence are if you are dealing with various +filtering/buffering scenarios, which are described in +:ref:`filtering_toplevel`, or if you want to programmatically +send content to the output stream, such as within a ``<% %>`` +block. + +.. sourcecode:: mako + + <% + context.write("some programmatic text") + %> + +The actual buffer may or may not be the original buffer sent to +the :class:`.Context` object, as various filtering/caching +scenarios may "push" a new buffer onto the context's underlying +buffer stack. For this reason, just stick with +``context.write()`` and content will always go to the topmost +buffer. + +.. _context_vars: + +Context Variables +----------------- + +When your template is compiled into a Python module, the body +content is enclosed within a Python function called +``render_body``. Other top-level defs defined in the template are +defined within their own function bodies which are named after +the def's name with the prefix ``render_`` (i.e. ``render_mydef``). +One of the first things that happens within these functions is +that all variable names that are referenced within the function +which are not defined in some other way (i.e. such as via +assignment, module level imports, etc.) are pulled from the +:class:`.Context` object's dictionary of variables. This is how you're +able to freely reference variable names in a template which +automatically correspond to what was passed into the current +:class:`.Context`. + +* **What happens if I reference a variable name that is not in + the current context?** - The value you get back is a special + value called ``UNDEFINED``, or if the ``strict_undefined=True`` flag + is used a ``NameError`` is raised. ``UNDEFINED`` is just a simple global + variable with the class :class:`mako.runtime.Undefined`. The + ``UNDEFINED`` object throws an error when you call ``str()`` on + it, which is what happens if you try to use it in an + expression. +* **UNDEFINED makes it hard for me to find what name is missing** - An alternative + is to specify the option ``strict_undefined=True`` + to the :class:`.Template` or :class:`.TemplateLookup`. This will cause + any non-present variables to raise an immediate ``NameError`` + which includes the name of the variable in its message + when :meth:`~.Template.render` is called -- ``UNDEFINED`` is not used. + + .. versionadded:: 0.3.6 + +* **Why not just return None?** Using ``UNDEFINED``, or + raising a ``NameError`` is more + explicit and allows differentiation between a value of ``None`` + that was explicitly passed to the :class:`.Context` and a value that + wasn't present at all. +* **Why raise an exception when you call str() on it ? Why not + just return a blank string?** - Mako tries to stick to the + Python philosophy of "explicit is better than implicit". In + this case, it's decided that the template author should be made + to specifically handle a missing value rather than + experiencing what may be a silent failure. Since ``UNDEFINED`` + is a singleton object just like Python's ``True`` or ``False``, + you can use the ``is`` operator to check for it: + + .. sourcecode:: mako + + % if someval is UNDEFINED: + someval is: no value + % else: + someval is: ${someval} + % endif + +Another facet of the :class:`.Context` is that its dictionary of +variables is **immutable**. Whatever is set when +:meth:`~.Template.render` is called is what stays. Of course, since +its Python, you can hack around this and change values in the +context's internal dictionary, but this will probably will not +work as well as you'd think. The reason for this is that Mako in +many cases creates copies of the :class:`.Context` object, which +get sent to various elements of the template and inheriting +templates used in an execution. So changing the value in your +local :class:`.Context` will not necessarily make that value +available in other parts of the template's execution. Examples +of where Mako creates copies of the :class:`.Context` include +within top-level def calls from the main body of the template +(the context is used to propagate locally assigned variables +into the scope of defs; since in the template's body they appear +as inlined functions, Mako tries to make them act that way), and +within an inheritance chain (each template in an inheritance +chain has a different notion of ``parent`` and ``next``, which +are all stored in unique :class:`.Context` instances). + +* **So what if I want to set values that are global to everyone + within a template request?** - All you have to do is provide a + dictionary to your :class:`.Context` when the template first + runs, and everyone can just get/set variables from that. Lets + say its called ``attributes``. + + Running the template looks like: + + .. sourcecode:: python + + output = template.render(attributes={}) + + Within a template, just reference the dictionary: + + .. sourcecode:: mako + + <% + attributes['foo'] = 'bar' + %> + 'foo' attribute is: ${attributes['foo']} + +* **Why can't "attributes" be a built-in feature of the + Context?** - This is an area where Mako is trying to make as + few decisions about your application as it possibly can. + Perhaps you don't want your templates to use this technique of + assigning and sharing data, or perhaps you have a different + notion of the names and kinds of data structures that should + be passed around. Once again Mako would rather ask the user to + be explicit. + +Context Methods and Accessors +----------------------------- + +Significant members of :class:`.Context` include: + +* ``context[key]`` / ``context.get(key, default=None)`` - + dictionary-like accessors for the context. Normally, any + variable you use in your template is automatically pulled from + the context if it isn't defined somewhere already. Use the + dictionary accessor and/or ``get`` method when you want a + variable that *is* already defined somewhere else, such as in + the local arguments sent to a ``%def`` call. If a key is not + present, like a dictionary it raises ``KeyError``. +* ``keys()`` - all the names defined within this context. +* ``kwargs`` - this returns a **copy** of the context's + dictionary of variables. This is useful when you want to + propagate the variables in the current context to a function + as keyword arguments, i.e.: + + .. sourcecode:: mako + + ${next.body(**context.kwargs)} + +* ``write(text)`` - write some text to the current output + stream. +* ``lookup`` - returns the :class:`.TemplateLookup` instance that is + used for all file-lookups within the current execution (even + though individual :class:`.Template` instances can conceivably have + different instances of a :class:`.TemplateLookup`, only the + :class:`.TemplateLookup` of the originally-called :class:`.Template` gets + used in a particular execution). + +.. _loop_context: + +The Loop Context +================ + +Within ``% for`` blocks, the :ref:`reserved name` ``loop`` +is available. ``loop`` tracks the progress of +the ``for`` loop and makes it easy to use the iteration state to control +template behavior: + +.. sourcecode:: mako + +
      + % for a in ("one", "two", "three"): +
    • Item ${loop.index}: ${a}
    • + % endfor +
    + +.. versionadded:: 0.7 + +Iterations +---------- + +Regardless of the type of iterable you're looping over, ``loop`` always tracks +the 0-indexed iteration count (available at ``loop.index``), its parity +(through the ``loop.even`` and ``loop.odd`` bools), and ``loop.first``, a bool +indicating whether the loop is on its first iteration. If your iterable +provides a ``__len__`` method, ``loop`` also provides access to +a count of iterations remaining at ``loop.reverse_index`` and ``loop.last``, +a bool indicating whether the loop is on its last iteration; accessing these +without ``__len__`` will raise a ``TypeError``. + +Cycling +------- + +Cycling is available regardless of whether the iterable you're using provides +a ``__len__`` method. Prior to Mako 0.7, you might have generated a simple +zebra striped list using ``enumerate``: + +.. sourcecode:: mako + +
      + % for i, item in enumerate(('spam', 'ham', 'eggs')): +
    • ${item}
    • + % endfor +
    + +With ``loop.cycle``, you get the same results with cleaner code and less prep work: + +.. sourcecode:: mako + +
      + % for item in ('spam', 'ham', 'eggs'): +
    • ${item}
    • + % endfor +
    + +Both approaches produce output like the following: + +.. sourcecode:: html + +
      +
    • spam
    • +
    • ham
    • +
    • eggs
    • +
    + +Parent Loops +------------ + +Loop contexts can also be transparently nested, and the Mako runtime will do +the right thing and manage the scope for you. You can access the parent loop +context through ``loop.parent``. + +This allows you to reach all the way back up through the loop stack by +chaining ``parent`` attribute accesses, i.e. ``loop.parent.parent....`` as +long as the stack depth isn't exceeded. For example, you can use the parent +loop to make a checkered table: + +.. sourcecode:: mako + +
+ % for consonant in 'pbj': + + % for vowel in 'iou': + + % endfor + + % endfor +
+ ${consonant + vowel}t +
+ +.. sourcecode:: html + + + + + + + + + + + + + + + + + +
+ pit + + pot + + put +
+ bit + + bot + + but +
+ jit + + jot + + jut +
+ +.. _migrating_loop: + +Migrating Legacy Templates that Use the Word "loop" +--------------------------------------------------- + +.. versionchanged:: 0.7 + The ``loop`` name is now :ref:`reserved ` in Mako, + which means a template that refers to a variable named ``loop`` + won't function correctly when used in Mako 0.7. + +To ease the transition for such systems, the feature can be disabled across the board for +all templates, then re-enabled on a per-template basis for those templates which wish +to make use of the new system. + +First, the ``enable_loop=False`` flag is passed to either the :class:`.TemplateLookup` +or :class:`.Template` object in use: + +.. sourcecode:: python + + lookup = TemplateLookup(directories=['/docs'], enable_loop=False) + +or: + +.. sourcecode:: python + + template = Template("some template", enable_loop=False) + +An individual template can make usage of the feature when ``enable_loop`` is set to +``False`` by switching it back on within the ``<%page>`` tag: + +.. sourcecode:: mako + + <%page enable_loop="True"/> + + % for i in collection: + ${i} ${loop.index} + % endfor + +Using the above scheme, it's safe to pass the name ``loop`` to the :meth:`.Template.render` +method as well as to freely make usage of a variable named ``loop`` within a template, provided +the ``<%page>`` tag doesn't override it. New templates that want to use the ``loop`` context +can then set up ``<%page enable_loop="True"/>`` to use the new feature without affecting +old templates. + +All the Built-in Names +====================== + +A one-stop shop for all the names Mako defines. Most of these +names are instances of :class:`.Namespace`, which are described +in the next section, :ref:`namespaces_toplevel`. Also, most of +these names other than ``context``, ``UNDEFINED``, and ``loop`` are +also present *within* the :class:`.Context` itself. The names +``context``, ``loop`` and ``UNDEFINED`` themselves can't be passed +to the context and can't be substituted -- see the section :ref:`reserved_names`. + +* ``context`` - this is the :class:`.Context` object, introduced + at :ref:`context`. +* ``local`` - the namespace of the current template, described + in :ref:`namespaces_builtin`. +* ``self`` - the namespace of the topmost template in an + inheritance chain (if any, otherwise the same as ``local``), + mostly described in :ref:`inheritance_toplevel`. +* ``parent`` - the namespace of the parent template in an + inheritance chain (otherwise undefined); see + :ref:`inheritance_toplevel`. +* ``next`` - the namespace of the next template in an + inheritance chain (otherwise undefined); see + :ref:`inheritance_toplevel`. +* ``caller`` - a "mini" namespace created when using the + ``<%call>`` tag to define a "def call with content"; described + in :ref:`defs_with_content`. +* ``loop`` - this provides access to :class:`.LoopContext` objects when + they are requested within ``% for`` loops, introduced at :ref:`loop_context`. +* ``capture`` - a function that calls a given def and captures + its resulting content into a string, which is returned. Usage + is described in :ref:`filtering_toplevel`. +* ``UNDEFINED`` - a global singleton that is applied to all + otherwise uninitialized template variables that were not + located within the :class:`.Context` when rendering began, + unless the :class:`.Template` flag ``strict_undefined`` + is set to ``True``. ``UNDEFINED`` is + an instance of :class:`.Undefined`, and raises an + exception when its ``__str__()`` method is called. +* ``pageargs`` - this is a dictionary which is present in a + template which does not define any ``**kwargs`` section in its + ``<%page>`` tag. All keyword arguments sent to the ``body()`` + function of a template (when used via namespaces) go here by + default unless otherwise defined as a page argument. If this + makes no sense, it shouldn't; read the section + :ref:`namespaces_body`. + +.. _reserved_names: + +Reserved Names +-------------- + +Mako has a few names that are considered to be "reserved" and can't be used +as variable names. + +.. versionchanged:: 0.7 + Mako raises an error if these words are found passed to the template + as context arguments, whereas in previous versions they'd be silently + ignored or lead to other error messages. + +* ``context`` - see :ref:`context`. +* ``UNDEFINED`` - see :ref:`context_vars`. +* ``loop`` - see :ref:`loop_context`. Note this can be disabled for legacy templates + via the ``enable_loop=False`` argument; see :ref:`migrating_loop`. + +API Reference +============= + +.. autoclass:: mako.runtime.Context + :show-inheritance: + :members: + +.. autoclass:: mako.runtime.LoopContext + :show-inheritance: + :members: + +.. autoclass:: mako.runtime.Undefined + :show-inheritance: + diff --git a/lib/mako-0.7.2/doc/_sources/syntax.txt b/lib/mako-0.7.2/doc/_sources/syntax.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/syntax.txt @@ -0,0 +1,469 @@ +.. _syntax_toplevel: + +====== +Syntax +====== + +A Mako template is parsed from a text stream containing any kind +of content, XML, HTML, email text, etc. The template can further +contain Mako-specific directives which represent variable and/or +expression substitutions, control structures (i.e. conditionals +and loops), server-side comments, full blocks of Python code, as +well as various tags that offer additional functionality. All of +these constructs compile into real Python code. This means that +you can leverage the full power of Python in almost every aspect +of a Mako template. + +Expression Substitution +======================= + +The simplest expression is just a variable substitution. The +syntax for this is the ``${}`` construct, which is inspired by +Perl, Genshi, JSP EL, and others: + +.. sourcecode:: mako + + this is x: ${x} + +Above, the string representation of ``x`` is applied to the +template's output stream. If you're wondering where ``x`` comes +from, it's usually from the :class:`.Context` supplied to the +template's rendering function. If ``x`` was not supplied to the +template and was not otherwise assigned locally, it evaluates to +a special value ``UNDEFINED``. More on that later. + +The contents within the ``${}`` tag are evaluated by Python +directly, so full expressions are OK: + +.. sourcecode:: mako + + pythagorean theorem: ${pow(x,2) + pow(y,2)} + +The results of the expression are evaluated into a string result +in all cases before being rendered to the output stream, such as +the above example where the expression produces a numeric +result. + +Expression Escaping +=================== + +Mako includes a number of built-in escaping mechanisms, +including HTML, URI and XML escaping, as well as a "trim" +function. These escapes can be added to an expression +substitution using the ``|`` operator: + +.. sourcecode:: mako + + ${"this is some text" | u} + +The above expression applies URL escaping to the expression, and +produces ``this+is+some+text``. The ``u`` name indicates URL +escaping, whereas ``h`` represents HTML escaping, ``x`` +represents XML escaping, and ``trim`` applies a trim function. + +Read more about built-in filtering functions, including how to +make your own filter functions, in :ref:`filtering_toplevel`. + +Control Structures +================== + +A control structure refers to all those things that control the +flow of a program -- conditionals (i.e. ``if``/``else``), loops (like +``while`` and ``for``), as well as things like ``try``/``except``. In Mako, +control structures are written using the ``%`` marker followed +by a regular Python control expression, and are "closed" by +using another ``%`` marker with the tag "``end``", where +"````" is the keyword of the expression: + +.. sourcecode:: mako + + % if x==5: + this is some output + % endif + +The ``%`` can appear anywhere on the line as long as no text +precedes it; indentation is not significant. The full range of +Python "colon" expressions are allowed here, including +``if``/``elif``/``else``, ``while``, ``for``, and even ``def``, although +Mako has a built-in tag for defs which is more full-featured. + +.. sourcecode:: mako + + % for a in ['one', 'two', 'three', 'four', 'five']: + % if a[0] == 't': + its two or three + % elif a[0] == 'f': + four/five + % else: + one + % endif + % endfor + +The ``%`` sign can also be "escaped", if you actually want to +emit a percent sign as the first non whitespace character on a +line, by escaping it as in ``%%``: + +.. sourcecode:: mako + + %% some text + + %% some more text + +The Loop Context +---------------- + +The **loop context** provides additional information about a loop +while inside of a ``% for`` structure: + +.. sourcecode:: mako + +
    + % for a in ("one", "two", "three"): +
  • Item ${loop.index}: ${a}
  • + % endfor +
+ +See :ref:`loop_context` for more information on this feature. + +.. versionadded:: 0.7 + +Comments +======== + +Comments come in two varieties. The single line comment uses +``##`` as the first non-space characters on a line: + +.. sourcecode:: mako + + ## this is a comment. + ...text ... + +A multiline version exists using ``<%doc> ...text... ``: + +.. sourcecode:: mako + + <%doc> + these are comments + more comments + + +Newline Filters +=============== + +The backslash ("``\``") character, placed at the end of any +line, will consume the newline character before continuing to +the next line: + +.. sourcecode:: mako + + here is a line that goes onto \ + another line. + +The above text evaluates to: + +.. sourcecode:: text + + here is a line that goes onto another line. + +Python Blocks +============= + +Any arbitrary block of python can be dropped in using the ``<% +%>`` tags: + +.. sourcecode:: mako + + this is a template + <% + x = db.get_resource('foo') + y = [z.element for z in x if x.frobnizzle==5] + %> + % for elem in y: + element: ${elem} + % endfor + +Within ``<% %>``, you're writing a regular block of Python code. +While the code can appear with an arbitrary level of preceding +whitespace, it has to be consistently formatted with itself. +Mako's compiler will adjust the block of Python to be consistent +with the surrounding generated Python code. + +Module-level Blocks +=================== + +A variant on ``<% %>`` is the module-level code block, denoted +by ``<%! %>``. Code within these tags is executed at the module +level of the template, and not within the rendering function of +the template. Therefore, this code does not have access to the +template's context and is only executed when the template is +loaded into memory (which can be only once per application, or +more, depending on the runtime environment). Use the ``<%! %>`` +tags to declare your template's imports, as well as any +pure-Python functions you might want to declare: + +.. sourcecode:: mako + + <%! + import mylib + import re + + def filter(text): + return re.sub(r'^@', '', text) + %> + +Any number of ``<%! %>`` blocks can be declared anywhere in a +template; they will be rendered in the resulting module +in a single contiguous block above all render callables, +in the order in which they appear in the source template. + +Tags +==== + +The rest of what Mako offers takes place in the form of tags. +All tags use the same syntax, which is similar to an XML tag +except that the first character of the tag name is a ``%`` +character. The tag is closed either by a contained slash +character, or an explicit closing tag: + +.. sourcecode:: mako + + <%include file="foo.txt"/> + + <%def name="foo" buffered="True"> + this is a def + + +All tags have a set of attributes which are defined for each +tag. Some of these attributes are required. Also, many +attributes support **evaluation**, meaning you can embed an +expression (using ``${}``) inside the attribute text: + +.. sourcecode:: mako + + <%include file="/foo/bar/${myfile}.txt"/> + +Whether or not an attribute accepts runtime evaluation depends +on the type of tag and how that tag is compiled into the +template. The best way to find out if you can stick an +expression in is to try it! The lexer will tell you if it's not +valid. + +Heres a quick summary of all the tags: + +``<%page>`` +----------- + +This tag defines general characteristics of the template, +including caching arguments, and optional lists of arguments +which the template expects when invoked. + +.. sourcecode:: mako + + <%page args="x, y, z='default'"/> + +Or a page tag that defines caching characteristics: + +.. sourcecode:: mako + + <%page cached="True" cache_type="memory"/> + +Currently, only one ``<%page>`` tag gets used per template, the +rest get ignored. While this will be improved in a future +release, for now make sure you have only one ``<%page>`` tag +defined in your template, else you may not get the results you +want. The details of what ``<%page>`` is used for are described +further in :ref:`namespaces_body` as well as :ref:`caching_toplevel`. + +``<%include>`` +-------------- + +A tag that is familiar from other template languages, ``%include`` +is a regular joe that just accepts a file argument and calls in +the rendered result of that file: + +.. sourcecode:: mako + + <%include file="header.html"/> + + hello world + + <%include file="footer.html"/> + +Include also accepts arguments which are available as ``<%page>`` arguments in the receiving template: + +.. sourcecode:: mako + + <%include file="toolbar.html" args="current_section='members', username='ed'"/> + +``<%def>`` +---------- + +The ``%def`` tag defines a Python function which contains a set +of content, that can be called at some other point in the +template. The basic idea is simple: + +.. sourcecode:: mako + + <%def name="myfunc(x)"> + this is myfunc, x is ${x} + + + ${myfunc(7)} + +The ``%def`` tag is a lot more powerful than a plain Python ``def``, as +the Mako compiler provides many extra services with ``%def`` that +you wouldn't normally have, such as the ability to export defs +as template "methods", automatic propagation of the current +:class:`.Context`, buffering/filtering/caching flags, and def calls +with content, which enable packages of defs to be sent as +arguments to other def calls (not as hard as it sounds). Get the +full deal on what ``%def`` can do in :ref:`defs_toplevel`. + +``<%block>`` +------------ + +``%block`` is a tag that is close to a ``%def``, +except executes itself immediately in its base-most scope, +and can also be anonymous (i.e. with no name): + +.. sourcecode:: mako + + <%block filter="h"> + some stuff. + + +Inspired by Jinja2 blocks, named blocks offer a syntactically pleasing way +to do inheritance: + +.. sourcecode:: mako + + + + <%block name="header"> +

<%block name="title"/>

+ + ${self.body()} + + + +Blocks are introduced in :ref:`blocks` and further described in :ref:`inheritance_toplevel`. + +.. versionadded:: 0.4.1 + +``<%namespace>`` +---------------- + +``%namespace`` is Mako's equivalent of Python's ``import`` +statement. It allows access to all the rendering functions and +metadata of other template files, plain Python modules, as well +as locally defined "packages" of functions. + +.. sourcecode:: mako + + <%namespace file="functions.html" import="*"/> + +The underlying object generated by ``%namespace``, an instance of +:class:`.mako.runtime.Namespace`, is a central construct used in +templates to reference template-specific information such as the +current URI, inheritance structures, and other things that are +not as hard as they sound right here. Namespaces are described +in :ref:`namespaces_toplevel`. + +``<%inherit>`` +-------------- + +Inherit allows templates to arrange themselves in **inheritance +chains**. This is a concept familiar in many other template +languages. + +.. sourcecode:: mako + + <%inherit file="base.html"/> + +When using the ``%inherit`` tag, control is passed to the topmost +inherited template first, which then decides how to handle +calling areas of content from its inheriting templates. Mako +offers a lot of flexibility in this area, including dynamic +inheritance, content wrapping, and polymorphic method calls. +Check it out in :ref:`inheritance_toplevel`. + +``<%``\ nsname\ ``:``\ defname\ ``>`` +------------------------------------- + +Any user-defined "tag" can be created against +a namespace by using a tag with a name of the form +``<%:>``. The closed and open formats of such a +tag are equivalent to an inline expression and the ``<%call>`` +tag, respectively. + +.. sourcecode:: mako + + <%mynamespace:somedef param="some value"> + this is the body + + +To create custom tags which accept a body, see +:ref:`defs_with_content`. + +.. versionadded:: 0.2.3 + +``<%call>`` +----------- + +The call tag is the "classic" form of a user-defined tag, and is +roughly equivalent to the ``<%namespacename:defname>`` syntax +described above. This tag is also described in :ref:`defs_with_content`. + +``<%doc>`` +---------- + +The ``%doc`` tag handles multiline comments: + +.. sourcecode:: mako + + <%doc> + these are comments + more comments + + +Also the ``##`` symbol as the first non-space characters on a line can be used for single line comments. + +``<%text>`` +----------- + +This tag suspends the Mako lexer's normal parsing of Mako +template directives, and returns its entire body contents as +plain text. It is used pretty much to write documentation about +Mako: + +.. sourcecode:: mako + + <%text filter="h"> + heres some fake mako ${syntax} + <%def name="x()">${x} + + +Returning Early from a Template +=============================== + +Sometimes you want to stop processing a template or ``<%def>`` +method in the middle and just use the text you've accumulated so +far. You can use a ``return`` statement inside a Python +block to do that. + +.. sourcecode:: mako + + % if not len(records): + No records found. + <% return %> + % endif + +Or perhaps: + +.. sourcecode:: mako + + <% + if not len(records): + return + %> + diff --git a/lib/mako-0.7.2/doc/_sources/unicode.txt b/lib/mako-0.7.2/doc/_sources/unicode.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/unicode.txt @@ -0,0 +1,345 @@ +.. _unicode_toplevel: + +=================== +The Unicode Chapter +=================== + +The Python language supports two ways of representing what we +know as "strings", i.e. series of characters. In Python 2, the +two types are ``string`` and ``unicode``, and in Python 3 they are +``bytes`` and ``string``. A key aspect of the Python 2 ``string`` and +Python 3 ``bytes`` types are that they contain no information +regarding what **encoding** the data is stored in. For this +reason they were commonly referred to as **byte strings** on +Python 2, and Python 3 makes this name more explicit. The +origins of this come from Python's background of being developed +before the Unicode standard was even available, back when +strings were C-style strings and were just that, a series of +bytes. Strings that had only values below 128 just happened to +be **ASCII** strings and were printable on the console, whereas +strings with values above 128 would produce all kinds of +graphical characters and bells. + +Contrast the "byte-string" type with the "unicode/string" type. +Objects of this latter type are created whenever you say something like +``u"hello world"`` (or in Python 3, just ``"hello world"``). In this +case, Python represents each character in the string internally +using multiple bytes per character (something similar to +UTF-16). What's important is that when using the +``unicode``/``string`` type to store strings, Python knows the +data's encoding; it's in its own internal format. Whereas when +using the ``string``/``bytes`` type, it does not. + +When Python 2 attempts to treat a byte-string as a string, which +means it's attempting to compare/parse its characters, to coerce +it into another encoding, or to decode it to a unicode object, +it has to guess what the encoding is. In this case, it will +pretty much always guess the encoding as ``ascii``... and if the +byte-string contains bytes above value 128, you'll get an error. +Python 3 eliminates much of this confusion by just raising an +error unconditionally if a byte-string is used in a +character-aware context. + +There is one operation that Python *can* do with a non-ASCII +byte-string, and it's a great source of confusion: it can dump the +byte-string straight out to a stream or a file, with nary a care +what the encoding is. To Python, this is pretty much like +dumping any other kind of binary data (like an image) to a +stream somewhere. In Python 2, it is common to see programs that +embed all kinds of international characters and encodings into +plain byte-strings (i.e. using ``"hello world"`` style literals) +can fly right through their run, sending reams of strings out to +wherever they are going, and the programmer, seeing the same +output as was expressed in the input, is now under the illusion +that his or her program is Unicode-compliant. In fact, their +program has no unicode awareness whatsoever, and similarly has +no ability to interact with libraries that *are* unicode aware. +Python 3 makes this much less likely by defaulting to unicode as +the storage format for strings. + +The "pass through encoded data" scheme is what template +languages like Cheetah and earlier versions of Myghty do by +default. Mako as of version 0.2 also supports this mode of +operation when using Python 2, using the ``disable_unicode=True`` +flag. However, when using Mako in its default mode of +unicode-aware, it requires explicitness when dealing with +non-ASCII encodings. Additionally, if you ever need to handle +unicode strings and other kinds of encoding conversions more +intelligently, the usage of raw byte-strings quickly becomes a +nightmare, since you are sending the Python interpreter +collections of bytes for which it can make no intelligent +decisions with regards to encoding. In Python 3 Mako only allows +usage of native, unicode strings. + +In normal Mako operation, all parsed template constructs and +output streams are handled internally as Python ``unicode`` +objects. It's only at the point of :meth:`~.Template.render` that this unicode +stream may be rendered into whatever the desired output encoding +is. The implication here is that the template developer must +:ensure that :ref:`the encoding of all non-ASCII templates is explicit +` (still required in Python 3), +that :ref:`all non-ASCII-encoded expressions are in one way or another +converted to unicode ` +(not much of a burden in Python 3), and that :ref:`the output stream of the +template is handled as a unicode stream being encoded to some +encoding ` (still required in Python 3). + +.. _set_template_file_encoding: + +Specifying the Encoding of a Template File +========================================== + +This is the most basic encoding-related setting, and it is +equivalent to Python's "magic encoding comment", as described in +`pep-0263 `_. Any +template that contains non-ASCII characters requires that this +comment be present so that Mako can decode to unicode (and also +make usage of Python's AST parsing services). Mako's lexer will +use this encoding in order to convert the template source into a +``unicode`` object before continuing its parsing: + +.. sourcecode:: mako + + ## -*- coding: utf-8 -*- + + Alors vous imaginez ma surprise, au lever du jour, quand + une dr?le de petite voix m?a r?veill?. Elle disait: + ? S?il vous pla?t? dessine-moi un mouton! ? + +For the picky, the regular expression used is derived from that +of the above mentioned pep: + +.. sourcecode:: python + + #.*coding[:=]\s*([-\w.]+).*\n + +The lexer will convert to unicode in all cases, so that if any +characters exist in the template that are outside of the +specified encoding (or the default of ``ascii``), the error will +be immediate. + +As an alternative, the template encoding can be specified +programmatically to either :class:`.Template` or :class:`.TemplateLookup` via +the ``input_encoding`` parameter: + +.. sourcecode:: python + + t = TemplateLookup(directories=['./'], input_encoding='utf-8') + +The above will assume all located templates specify ``utf-8`` +encoding, unless the template itself contains its own magic +encoding comment, which takes precedence. + +.. _handling_non_ascii_expressions: + +Handling Expressions +==================== + +The next area that encoding comes into play is in expression +constructs. By default, Mako's treatment of an expression like +this: + +.. sourcecode:: mako + + ${"hello world"} + +looks something like this: + +.. sourcecode:: python + + context.write(unicode("hello world")) + +In Python 3, it's just: + +.. sourcecode:: python + + context.write(str("hello world")) + +That is, **the output of all expressions is run through the +``unicode`` built-in**. This is the default setting, and can be +modified to expect various encodings. The ``unicode`` step serves +both the purpose of rendering non-string expressions into +strings (such as integers or objects which contain ``__str()__`` +methods), and to ensure that the final output stream is +constructed as a unicode object. The main implication of this is +that **any raw byte-strings that contain an encoding other than +ASCII must first be decoded to a Python unicode object**. It +means you can't say this in Python 2: + +.. sourcecode:: mako + + ${"voix m?a r?veill?."} ## error in Python 2! + +You must instead say this: + +.. sourcecode:: mako + + ${u"voix m?a r?veill?."} ## OK ! + +Similarly, if you are reading data from a file that is streaming +bytes, or returning data from some object that is returning a +Python byte-string containing a non-ASCII encoding, you have to +explicitly decode to unicode first, such as: + +.. sourcecode:: mako + + ${call_my_object().decode('utf-8')} + +Note that filehandles acquired by ``open()`` in Python 3 default +to returning "text", that is the decoding is done for you. See +Python 3's documentation for the ``open()`` built-in for details on +this. + +If you want a certain encoding applied to *all* expressions, +override the ``unicode`` builtin with the ``decode`` built-in at the +:class:`.Template` or :class:`.TemplateLookup` level: + +.. sourcecode:: python + + t = Template(templatetext, default_filters=['decode.utf8']) + +Note that the built-in ``decode`` object is slower than the +``unicode`` function, since unlike ``unicode`` it's not a Python +built-in, and it also checks the type of the incoming data to +determine if string conversion is needed first. + +The ``default_filters`` argument can be used to entirely customize +the filtering process of expressions. This argument is described +in :ref:`filtering_default_filters`. + +.. _defining_output_encoding: + +Defining Output Encoding +======================== + +Now that we have a template which produces a pure unicode output +stream, all the hard work is done. We can take the output and do +anything with it. + +As stated in the :doc:`"Usage" chapter `, both :class:`.Template` and +:class:`.TemplateLookup` accept ``output_encoding`` and ``encoding_errors`` +parameters which can be used to encode the output in any Python +supported codec: + +.. sourcecode:: python + + from mako.template import Template + from mako.lookup import TemplateLookup + + mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace') + + mytemplate = mylookup.get_template("foo.txt") + print mytemplate.render() + +:meth:`~.Template.render` will return a ``bytes`` object in Python 3 if an output +encoding is specified. By default it performs no encoding and +returns a native string. + +:meth:`~.Template.render_unicode` will return the template output as a Python +``unicode`` object (or ``string`` in Python 3): + +.. sourcecode:: python + + print mytemplate.render_unicode() + +The above method disgards the output encoding keyword argument; +you can encode yourself by saying: + +.. sourcecode:: python + + print mytemplate.render_unicode().encode('utf-8', 'replace') + +Buffer Selection +---------------- + +Mako does play some games with the style of buffering used +internally, to maximize performance. Since the buffer is by far +the most heavily used object in a render operation, it's +important! + +When calling :meth:`~.Template.render` on a template that does not specify any +output encoding (i.e. it's ``ascii``), Python's ``cStringIO`` module, +which cannot handle encoding of non-ASCII ``unicode`` objects +(even though it can send raw byte-strings through), is used for +buffering. Otherwise, a custom Mako class called +``FastEncodingBuffer`` is used, which essentially is a super +dumbed-down version of ``StringIO`` that gathers all strings into +a list and uses ``u''.join(elements)`` to produce the final output +-- it's markedly faster than ``StringIO``. + +.. _unicode_disabled: + +Saying to Heck with It: Disabling the Usage of Unicode Entirely +=============================================================== + +Some segments of Mako's userbase choose to make no usage of +Unicode whatsoever, and instead would prefer the "pass through" +approach; all string expressions in their templates return +encoded byte-strings, and they would like these strings to pass +right through. The only advantage to this approach is that +templates need not use ``u""`` for literal strings; there's an +arguable speed improvement as well since raw byte-strings +generally perform slightly faster than unicode objects in +Python. For these users, assuming they're sticking with Python +2, they can hit the ``disable_unicode=True`` flag as so: + +.. sourcecode:: python + + # -*- encoding:utf-8 -*- + from mako.template import Template + + t = Template("dr?le de petite voix m?a r?veill?.", disable_unicode=True, input_encoding='utf-8') + print t.code + +The ``disable_unicode`` mode is strictly a Python 2 thing. It is +not supported at all in Python 3. + +The generated module source code will contain elements like +these: + +.. sourcecode:: python + + # -*- encoding:utf-8 -*- + # ...more generated code ... + + def render_body(context,**pageargs): + context.caller_stack.push_frame() + try: + __M_locals = dict(pageargs=pageargs) + # SOURCE LINE 1 + context.write('dr\xc3\xb4le de petite voix m\xe2\x80\x99a r\xc3\xa9veill\xc3\xa9.') + return '' + finally: + context.caller_stack.pop_frame() + +Where above that the string literal used within :meth:`.Context.write` +is a regular byte-string. + +When ``disable_unicode=True`` is turned on, the ``default_filters`` +argument which normally defaults to ``["unicode"]`` now defaults +to ``["str"]`` instead. Setting ``default_filters`` to the empty list +``[]`` can remove the overhead of the ``str`` call. Also, in this +mode you **cannot** safely call :meth:`~.Template.render_unicode` -- you'll get +unicode/decode errors. + +The ``h`` filter (HTML escape) uses a less performant pure Python +escape function in non-unicode mode. This because +MarkupSafe only supports Python unicode objects for non-ASCII +strings. + +.. versionchanged:: 0.3.4 + In prior versions, it used ``cgi.escape()``, which has been replaced + with a function that also escapes single quotes. + +Rules for using ``disable_unicode=True`` +---------------------------------------- + +* Don't use this mode unless you really, really want to and you + absolutely understand what you're doing. +* Don't use this option just because you don't want to learn to + use Unicode properly; we aren't supporting user issues in this + mode of operation. We will however offer generous help for the + vast majority of users who stick to the Unicode program. +* Python 3 is unicode by default, and the flag is not available + when running on Python 3. + diff --git a/lib/mako-0.7.2/doc/_sources/usage.txt b/lib/mako-0.7.2/doc/_sources/usage.txt new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_sources/usage.txt @@ -0,0 +1,520 @@ +.. _usage_toplevel: + +===== +Usage +===== + +Basic Usage +=========== + +This section describes the Python API for Mako templates. If you +are using Mako within a web framework such as Pylons, the work +of integrating Mako's API is already done for you, in which case +you can skip to the next section, :ref:`syntax_toplevel`. + +The most basic way to create a template and render it is through +the :class:`.Template` class: + +.. sourcecode:: python + + from mako.template import Template + + mytemplate = Template("hello world!") + print mytemplate.render() + +Above, the text argument to :class:`.Template` is **compiled** into a +Python module representation. This module contains a function +called ``render_body()``, which produces the output of the +template. When ``mytemplate.render()`` is called, Mako sets up a +runtime environment for the template and calls the +``render_body()`` function, capturing the output into a buffer and +returning its string contents. + + +The code inside the ``render_body()`` function has access to a +namespace of variables. You can specify these variables by +sending them as additional keyword arguments to the :meth:`~.Template.render` +method: + +.. sourcecode:: python + + from mako.template import Template + + mytemplate = Template("hello, ${name}!") + print mytemplate.render(name="jack") + +The :meth:`~.Template.render` method calls upon Mako to create a +:class:`.Context` object, which stores all the variable names accessible +to the template and also stores a buffer used to capture output. +You can create this :class:`.Context` yourself and have the template +render with it, using the :meth:`~.Template.render_context` method: + +.. sourcecode:: python + + from mako.template import Template + from mako.runtime import Context + from StringIO import StringIO + + mytemplate = Template("hello, ${name}!") + buf = StringIO() + ctx = Context(buf, name="jack") + mytemplate.render_context(ctx) + print buf.getvalue() + +Using File-Based Templates +========================== + +A :class:`.Template` can also load its template source code from a file, +using the ``filename`` keyword argument: + +.. sourcecode:: python + + from mako.template import Template + + mytemplate = Template(filename='/docs/mytmpl.txt') + print mytemplate.render() + +For improved performance, a :class:`.Template` which is loaded from a +file can also cache the source code to its generated module on +the filesystem as a regular Python module file (i.e. a ``.py`` +file). To do this, just add the ``module_directory`` argument to +the template: + +.. sourcecode:: python + + from mako.template import Template + + mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules') + print mytemplate.render() + +When the above code is rendered, a file +``/tmp/mako_modules/docs/mytmpl.txt.py`` is created containing the +source code for the module. The next time a :class:`.Template` with the +same arguments is created, this module file will be +automatically re-used. + +.. _usage_templatelookup: + +Using ``TemplateLookup`` +======================== + +All of the examples thus far have dealt with the usage of a +single :class:`.Template` object. If the code within those templates +tries to locate another template resource, it will need some way +to find them, using simple URI strings. For this need, the +resolution of other templates from within a template is +accomplished by the :class:`.TemplateLookup` class. This class is +constructed given a list of directories in which to search for +templates, as well as keyword arguments that will be passed to +the :class:`.Template` objects it creates: + +.. sourcecode:: python + + from mako.template import Template + from mako.lookup import TemplateLookup + + mylookup = TemplateLookup(directories=['/docs']) + mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup) + +Above, we created a textual template which includes the file +``"header.txt"``. In order for it to have somewhere to look for +``"header.txt"``, we passed a :class:`.TemplateLookup` object to it, which +will search in the directory ``/docs`` for the file ``"header.txt"``. + +Usually, an application will store most or all of its templates +as text files on the filesystem. So far, all of our examples +have been a little bit contrived in order to illustrate the +basic concepts. But a real application would get most or all of +its templates directly from the :class:`.TemplateLookup`, using the +aptly named :meth:`~.TemplateLookup.get_template` method, which accepts the URI of the +desired template: + +.. sourcecode:: python + + from mako.template import Template + from mako.lookup import TemplateLookup + + mylookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules') + + def serve_template(templatename, **kwargs): + mytemplate = mylookup.get_template(templatename) + print mytemplate.render(**kwargs) + +In the example above, we create a :class:`.TemplateLookup` which will +look for templates in the ``/docs`` directory, and will store +generated module files in the ``/tmp/mako_modules`` directory. The +lookup locates templates by appending the given URI to each of +its search directories; so if you gave it a URI of +``/etc/beans/info.txt``, it would search for the file +``/docs/etc/beans/info.txt``, else raise a :class:`.TopLevelNotFound` +exception, which is a custom Mako exception. + +When the lookup locates templates, it will also assign a ``uri`` +property to the :class:`.Template` which is the URI passed to the +:meth:`~.TemplateLookup.get_template()` call. :class:`.Template` uses this URI to calculate the +name of its module file. So in the above example, a +``templatename`` argument of ``/etc/beans/info.txt`` will create a +module file ``/tmp/mako_modules/etc/beans/info.txt.py``. + +Setting the Collection Size +--------------------------- + +The :class:`.TemplateLookup` also serves the important need of caching a +fixed set of templates in memory at a given time, so that +successive URI lookups do not result in full template +compilations and/or module reloads on each request. By default, +the :class:`.TemplateLookup` size is unbounded. You can specify a fixed +size using the ``collection_size`` argument: + +.. sourcecode:: python + + mylookup = TemplateLookup(directories=['/docs'], + module_directory='/tmp/mako_modules', collection_size=500) + +The above lookup will continue to load templates into memory +until it reaches a count of around 500. At that point, it will +clean out a certain percentage of templates using a least +recently used scheme. + +Setting Filesystem Checks +------------------------- + +Another important flag on :class:`.TemplateLookup` is +``filesystem_checks``. This defaults to ``True``, and says that each +time a template is returned by the :meth:`~.TemplateLookup.get_template()` method, the +revision time of the original template file is checked against +the last time the template was loaded, and if the file is newer +will reload its contents and recompile the template. On a +production system, setting ``filesystem_checks`` to ``False`` can +afford a small to moderate performance increase (depending on +the type of filesystem used). + +.. _usage_unicode: + +Using Unicode and Encoding +========================== + +Both :class:`.Template` and :class:`.TemplateLookup` accept ``output_encoding`` +and ``encoding_errors`` parameters which can be used to encode the +output in any Python supported codec: + +.. sourcecode:: python + + from mako.template import Template + from mako.lookup import TemplateLookup + + mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace') + + mytemplate = mylookup.get_template("foo.txt") + print mytemplate.render() + +When using Python 3, the :meth:`~.Template.render` method will return a ``bytes`` +object, **if** ``output_encoding`` is set. Otherwise it returns a +``string``. + +Additionally, the :meth:`~.Template.render_unicode()` method exists which will +return the template output as a Python ``unicode`` object, or in +Python 3 a ``string``: + +.. sourcecode:: python + + print mytemplate.render_unicode() + +The above method disregards the output encoding keyword +argument; you can encode yourself by saying: + +.. sourcecode:: python + + print mytemplate.render_unicode().encode('utf-8', 'replace') + +Note that Mako's ability to return data in any encoding and/or +``unicode`` implies that the underlying output stream of the +template is a Python unicode object. This behavior is described +fully in :ref:`unicode_toplevel`. + +.. _handling_exceptions: + +Handling Exceptions +=================== + +Template exceptions can occur in two distinct places. One is +when you **lookup, parse and compile** the template, the other +is when you **run** the template. Within the running of a +template, exceptions are thrown normally from whatever Python +code originated the issue. Mako has its own set of exception +classes which mostly apply to the lookup and lexer/compiler +stages of template construction. Mako provides some library +routines that can be used to help provide Mako-specific +information about any exception's stack trace, as well as +formatting the exception within textual or HTML format. In all +cases, the main value of these handlers is that of converting +Python filenames, line numbers, and code samples into Mako +template filenames, line numbers, and code samples. All lines +within a stack trace which correspond to a Mako template module +will be converted to be against the originating template file. + +To format exception traces, the :func:`.text_error_template` and +:func:`.html_error_template` functions are provided. They make usage of +``sys.exc_info()`` to get at the most recently thrown exception. +Usage of these handlers usually looks like: + +.. sourcecode:: python + + from mako import exceptions + + try: + template = lookup.get_template(uri) + print template.render() + except: + print exceptions.text_error_template().render() + +Or for the HTML render function: + +.. sourcecode:: python + + from mako import exceptions + + try: + template = lookup.get_template(uri) + print template.render() + except: + print exceptions.html_error_template().render() + +The :func:`.html_error_template` template accepts two options: +specifying ``full=False`` causes only a section of an HTML +document to be rendered. Specifying ``css=False`` will disable the +default stylesheet from being rendered. + +E.g.: + +.. sourcecode:: python + + print exceptions.html_error_template().render(full=False) + +The HTML render function is also available built-in to +:class:`.Template` using the ``format_exceptions`` flag. In this case, any +exceptions raised within the **render** stage of the template +will result in the output being substituted with the output of +:func:`.html_error_template`: + +.. sourcecode:: python + + template = Template(filename="/foo/bar", format_exceptions=True) + print template.render() + +Note that the compile stage of the above template occurs when +you construct the :class:`.Template` itself, and no output stream is +defined. Therefore exceptions which occur within the +lookup/parse/compile stage will not be handled and will +propagate normally. While the pre-render traceback usually will +not include any Mako-specific lines anyway, it will mean that +exceptions which occur previous to rendering and those which +occur within rendering will be handled differently... so the +``try``/``except`` patterns described previously are probably of more +general use. + +The underlying object used by the error template functions is +the :class:`.RichTraceback` object. This object can also be used +directly to provide custom error views. Here's an example usage +which describes its general API: + +.. sourcecode:: python + + from mako.exceptions import RichTraceback + + try: + template = lookup.get_template(uri) + print template.render() + except: + traceback = RichTraceback() + for (filename, lineno, function, line) in traceback.traceback: + print "File %s, line %s, in %s" % (filename, lineno, function) + print line, "\n" + print "%s: %s" % (str(traceback.error.__class__.__name__), traceback.error) + +Common Framework Integrations +============================= + +The Mako distribution includes a little bit of helper code for +the purpose of using Mako in some popular web framework +scenarios. This is a brief description of what's included. + +WSGI +---- + +A sample WSGI application is included in the distribution in the +file ``examples/wsgi/run_wsgi.py``. This runner is set up to pull +files from a `templates` as well as an `htdocs` directory and +includes a rudimental two-file layout. The WSGI runner acts as a +fully functional standalone web server, using ``wsgiutils`` to run +itself, and propagates GET and POST arguments from the request +into the :class:`.Context`, can serve images, CSS files and other kinds +of files, and also displays errors using Mako's included +exception-handling utilities. + +Pygments +-------- + +A `Pygments `_-compatible syntax +highlighting module is included under :mod:`mako.ext.pygmentplugin`. +This module is used in the generation of Mako documentation and +also contains various `setuptools` entry points under the heading +``pygments.lexers``, including ``mako``, ``html+mako``, ``xml+mako`` +(see the ``setup.py`` file for all the entry points). + +Babel +----- + +Mako provides support for extracting `gettext` messages from +templates via a `Babel`_ extractor +entry point under ``mako.ext.babelplugin``. + +`Gettext` messages are extracted from all Python code sections, +including those of control lines and expressions embedded +in tags. + +`Translator +comments `_ +may also be extracted from Mako templates when a comment tag is +specified to `Babel`_ (such as with +the ``-c`` option). + +For example, a project ``"myproj"`` contains the following Mako +template at ``myproj/myproj/templates/name.html``: + +.. sourcecode:: mako + +
+ Name: + ## TRANSLATORS: This is a proper name. See the gettext + ## manual, section Names. + ${_('Francois Pinard')} +
+ +To extract gettext messages from this template the project needs +a Mako section in its `Babel Extraction Method Mapping +file `_ +(typically located at ``myproj/babel.cfg``): + +.. sourcecode:: cfg + + # Extraction from Python source files + + [python: myproj/**.py] + + # Extraction from Mako templates + + [mako: myproj/templates/**.html] + input_encoding = utf-8 + +The Mako extractor supports an optional ``input_encoding`` +parameter specifying the encoding of the templates (identical to +:class:`.Template`/:class:`.TemplateLookup`'s ``input_encoding`` parameter). + +Invoking `Babel`_'s extractor at the +command line in the project's root directory: + +.. sourcecode:: sh + + myproj$ pybabel extract -F babel.cfg -c "TRANSLATORS:" . + +will output a `gettext` catalog to `stdout` including the following: + +.. sourcecode:: pot + + #. TRANSLATORS: This is a proper name. See the gettext + #. manual, section Names. + #: myproj/templates/name.html:5 + msgid "Francois Pinard" + msgstr "" + +This is only a basic example: +`Babel`_ can be invoked from ``setup.py`` +and its command line options specified in the accompanying +``setup.cfg`` via `Babel Distutils/Setuptools +Integration `_. + +Comments must immediately precede a `gettext` message to be +extracted. In the following case the ``TRANSLATORS:`` comment would +not have been extracted: + +.. sourcecode:: mako + +
+ ## TRANSLATORS: This is a proper name. See the gettext + ## manual, section Names. + Name: ${_('Francois Pinard')} +
+ +See the `Babel User +Guide `_ +for more information. + +.. _babel: http://babel.edgewall.org/ + + +API Reference +============= + +.. autoclass:: mako.template.Template + :show-inheritance: + :members: + +.. autoclass:: mako.template.DefTemplate + :show-inheritance: + :members: + +.. autoclass:: mako.lookup.TemplateCollection + :show-inheritance: + :members: + +.. autoclass:: mako.lookup.TemplateLookup + :show-inheritance: + :members: + +.. autoclass:: mako.exceptions.RichTraceback + :show-inheritance: + + .. py:attribute:: error + + the exception instance. + + .. py:attribute:: message + + the exception error message as unicode. + + .. py:attribute:: source + + source code of the file where the error occurred. + If the error occurred within a compiled template, + this is the template source. + + .. py:attribute:: lineno + + line number where the error occurred. If the error + occurred within a compiled template, the line number + is adjusted to that of the template source. + + .. py:attribute:: records + + a list of 8-tuples containing the original + python traceback elements, plus the + filename, line number, source line, and full template source + for the traceline mapped back to its originating source + template, if any for that traceline (else the fields are ``None``). + + .. py:attribute:: reverse_records + + the list of records in reverse + traceback -- a list of 4-tuples, in the same format as a regular + python traceback, with template-corresponding + traceback records replacing the originals. + + .. py:attribute:: reverse_traceback + + the traceback list in reverse. + +.. autofunction:: mako.exceptions.html_error_template + +.. autofunction:: mako.exceptions.text_error_template + diff --git a/lib/mako-0.7.2/doc/_static/basic.css b/lib/mako-0.7.2/doc/_static/basic.css new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_static/basic.css @@ -0,0 +1,540 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + width: 170px; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + width: 30px; +} + +img { + border: 0; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.refcount { + color: #060; +} + +.optional { + font-size: 1.3em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +tt.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +tt.descclassname { + background-color: transparent; +} + +tt.xref, a tt { + background-color: transparent; + font-weight: bold; +} + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + + at media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/lib/mako-0.7.2/doc/_static/comment-bright.png b/lib/mako-0.7.2/doc/_static/comment-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..551517b8c83b76f734ff791f847829a760ad1903 GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/comment-close.png b/lib/mako-0.7.2/doc/_static/comment-close.png new file mode 100644 index 0000000000000000000000000000000000000000..09b54be46da3f0d4a5061da289dc91d8a2cdbc9c GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/comment.png b/lib/mako-0.7.2/doc/_static/comment.png new file mode 100644 index 0000000000000000000000000000000000000000..92feb52b8824c6b0f59b658b1196c61de9162a95 GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/default.css b/lib/mako-0.7.2/doc/_static/default.css new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_static/default.css @@ -0,0 +1,256 @@ +/* + * default.css_t + * ~~~~~~~~~~~~~ + * + * Sphinx stylesheet -- default theme. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + + at import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: sans-serif; + font-size: 100%; + background-color: #11303d; + color: #000; + margin: 0; + padding: 0; +} + +div.document { + background-color: #1c4e63; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 230px; +} + +div.body { + background-color: #ffffff; + color: #000000; + padding: 0 20px 30px 20px; +} + +div.footer { + color: #ffffff; + width: 100%; + padding: 9px 0 9px 0; + text-align: center; + font-size: 75%; +} + +div.footer a { + color: #ffffff; + text-decoration: underline; +} + +div.related { + background-color: #133f52; + line-height: 30px; + color: #ffffff; +} + +div.related a { + color: #ffffff; +} + +div.sphinxsidebar { +} + +div.sphinxsidebar h3 { + font-family: 'Trebuchet MS', sans-serif; + color: #ffffff; + font-size: 1.4em; + font-weight: normal; + margin: 0; + padding: 0; +} + +div.sphinxsidebar h3 a { + color: #ffffff; +} + +div.sphinxsidebar h4 { + font-family: 'Trebuchet MS', sans-serif; + color: #ffffff; + font-size: 1.3em; + font-weight: normal; + margin: 5px 0 0 0; + padding: 0; +} + +div.sphinxsidebar p { + color: #ffffff; +} + +div.sphinxsidebar p.topless { + margin: 5px 10px 10px 10px; +} + +div.sphinxsidebar ul { + margin: 10px; + padding: 0; + color: #ffffff; +} + +div.sphinxsidebar a { + color: #98dbcc; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + + + +/* -- hyperlink styles ------------------------------------------------------ */ + +a { + color: #355f7c; + text-decoration: none; +} + +a:visited { + color: #355f7c; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + + + +/* -- body styles ----------------------------------------------------------- */ + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: 'Trebuchet MS', sans-serif; + background-color: #f2f2f2; + font-weight: normal; + color: #20435c; + border-bottom: 1px solid #ccc; + margin: 20px -20px 10px -20px; + padding: 3px 0 3px 10px; +} + +div.body h1 { margin-top: 0; font-size: 200%; } +div.body h2 { font-size: 160%; } +div.body h3 { font-size: 140%; } +div.body h4 { font-size: 120%; } +div.body h5 { font-size: 110%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #c60f0f; + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + background-color: #c60f0f; + color: white; +} + +div.body p, div.body dd, div.body li { + text-align: justify; + line-height: 130%; +} + +div.admonition p.admonition-title + p { + display: inline; +} + +div.admonition p { + margin-bottom: 5px; +} + +div.admonition pre { + margin-bottom: 5px; +} + +div.admonition ul, div.admonition ol { + margin-bottom: 5px; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre { + padding: 5px; + background-color: #eeffcc; + color: #333333; + line-height: 120%; + border: 1px solid #ac9; + border-left: none; + border-right: none; +} + +tt { + background-color: #ecf0f3; + padding: 0 1px 0 1px; + font-size: 0.95em; +} + +th { + background-color: #ede; +} + +.warning tt { + background: #efc2c2; +} + +.note tt { + background: #d6d6d6; +} + +.viewcode-back { + font-family: sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} \ No newline at end of file diff --git a/lib/mako-0.7.2/doc/_static/docs.css b/lib/mako-0.7.2/doc/_static/docs.css new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_static/docs.css @@ -0,0 +1,438 @@ +/* global */ + +body { + background-color: #FDFBFC; + margin:38px; + color:#333333; +} + +a { + font-weight:normal; + text-decoration:none; +} + +form { + display:inline; +} + +/* hyperlinks */ + +a:link, a:visited, a:active { + color:#0000FF; +} +a:hover { + color:#700000; + text-decoration:underline; +} + +/* paragraph links after sections. + These aren't visible until hovering + over the tag, then have a + "reverse video" effect over the actual + link + */ + +a.headerlink { + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +a.headerlink:hover { + background-color: #990000; + color: white; +} + + +/* Container setup */ + +#docs-container { + max-width:1000px; +} + + +/* header/footer elements */ + +#docs-header h1 { + font-size:20px; + color: #222222; + margin: 0; + padding: 0; +} + +#docs-header { + font-family:Tahoma, Geneva,sans-serif; + + font-size:.9em; + +} + +#docs-top-navigation, +#docs-bottom-navigation { + font-family: Tahoma, Geneva, sans-serif; + background-color: #EEE; + border: solid 1px #CCC; + padding:10px; + font-size:.9em; +} + +#docs-top-navigation { + margin:10px 0px 10px 0px; + line-height:1.2em; +} + +.docs-navigation-links { + font-family:Tahoma, Geneva,sans-serif; +} + +#docs-bottom-navigation { + float:right; + margin: 1em 0 1em 5px; +} + +#docs-copyright { + font-size:.85em; + padding:5px 0px; +} + +#docs-header h1, +#docs-top-navigation h1, +#docs-top-navigation h2 { + font-family:Tahoma,Geneva,sans-serif; + font-weight:normal; +} + +#docs-top-navigation h2 { + margin:16px 4px 7px 5px; + font-size:2em; +} + +#docs-search { + float:right; +} + +#docs-top-page-control { + float:right; + width:350px; +} + +#docs-top-page-control ul { + padding:0; + margin:0; +} + +#docs-top-page-control li { + list-style-type:none; + padding:1px 8px; +} + + +#docs-container .version-num { + font-weight: bold; +} + + +/* content container, sidebar */ + +#docs-body-container { + background-color:#EFEFEF; + border: solid 1px #CCC; + +} + +#docs-body, +#docs-sidebar + { + /*font-family: helvetica, arial, sans-serif; + font-size:.9em;*/ + + font-family: Tahoma, Geneva, sans-serif; + /*font-size:.85em;*/ + line-height:1.5em; + +} + +#docs-sidebar > ul { + font-size:.9em; +} + +#docs-sidebar { + float:left; + width:212px; + padding: 10px 0 0 15px; + /*font-size:.85em;*/ +} + +#docs-sidebar h3, #docs-sidebar h4 { + background-color: #DDDDDD; + color: #222222; + font-family: Tahoma, Geneva,sans-serif; + font-size: 1.1em; + font-weight: normal; + margin: 10px 0 0 -15px; + padding: 5px 10px 5px 10px; + text-shadow: 1px 1px 0 white; + width:210px; +} + +#docs-sidebar h3 a, #docs-sidebar h4 a { + color: #222222; +} +#docs-sidebar ul { + margin: 10px 10px 10px 0px; + padding: 0; + list-style: none outside none; +} + + +#docs-sidebar ul ul { + margin-bottom: 0; + margin-top: 0; + list-style: square outside none; + margin-left: 20px; +} + +#docs-body { + background-color:#FFFFFF; + padding:1px 10px 10px 10px; +} + +#docs-body.withsidebar { + margin: 0 0 0 230px; + border-left:3px solid #DFDFDF; +} + +#docs-body h1, +#docs-body h2, +#docs-body h3, +#docs-body h4 { + font-family:Tahoma, Geneva, sans-serif; +} + +#docs-body h1 { + /* hide the

for each content section. */ + display:none; + font-size:1.8em; +} + +#docs-body h2 { + font-size:1.6em; +} + +#docs-body h3 { + font-size:1.4em; +} + +/* SQL popup, code styles */ + +.highlight { + background:none; +} + +#docs-container pre { + font-size:1.2em; +} + +#docs-container .pre { + font-size:1.1em; +} + +#docs-container pre { + background-color: #f0f0f0; + border: solid 1px #ccc; + box-shadow: 2px 2px 3px #DFDFDF; + padding:10px; + margin: 5px 0px 5px 0px; + overflow:auto; + line-height:1.3em; +} + +.popup_sql, .show_sql +{ + background-color: #FBFBEE; + padding:5px 10px; + margin:10px -5px; + border:1px dashed; +} + +/* the [SQL] links used to display SQL */ +#docs-container .sql_link +{ + font-weight:normal; + font-family: arial, sans-serif; + font-size:.9em; + text-transform: uppercase; + color:#990000; + border:1px solid; + padding:1px 2px 1px 2px; + margin:0px 10px 0px 15px; + float:right; + line-height:1.2em; +} + +#docs-container a.sql_link, +#docs-container .sql_link +{ + text-decoration: none; + padding:1px 2px; +} + +#docs-container a.sql_link:hover { + text-decoration: none; + color:#fff; + border:1px solid #900; + background-color: #900; +} + +/* docutils-specific elements */ + +th.field-name { + text-align:right; +} + +div.note, div.warning, p.deprecated, div.topic { + background-color:#EEFFEF; +} + + +div.admonition, div.topic, p.deprecated, p.versionadded, p.versionchanged { + border:1px solid #CCCCCC; + padding:5px 10px; + font-size:.9em; + box-shadow: 2px 2px 3px #DFDFDF; +} + +div.warning .admonition-title { + color:#FF0000; +} + +div.admonition .admonition-title, div.topic .topic-title { + font-weight:bold; +} + +.viewcode-back, .viewcode-link { + float:right; +} + +dl.function > dt, +dl.attribute > dt, +dl.classmethod > dt, +dl.method > dt, +dl.class > dt, +dl.exception > dt +{ + background-color:#F0F0F0; + margin:25px -10px 10px 10px; + padding: 0px 10px; +} + +p.versionadded span.versionmodified, +p.versionchanged span.versionmodified, +p.deprecated span.versionmodified { + background-color: #F0F0F0; + font-style: italic; +} + +dt:target, span.highlight { + background-color:#FBE54E; +} + +a.headerlink { + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +a.headerlink:hover { + background-color: #00f; + color: white; +} + +.clearboth { + clear:both; +} + +tt.descname { + background-color:transparent; + font-size:1.2em; + font-weight:bold; +} + +tt.descclassname { + background-color:transparent; +} + +tt { + background-color:#ECF0F3; + padding:0 1px; +} + +/* syntax highlighting overrides */ +.k, .kn {color:#0908CE;} +.o {color:#BF0005;} +.go {color:#804049;} + + +/* special "index page" sections + with specific formatting +*/ + +div#sqlalchemy-documentation { + font-size:.95em; +} +div#sqlalchemy-documentation em { + font-style:normal; +} +div#sqlalchemy-documentation .rubric{ + font-size:14px; + background-color:#EEFFEF; + padding:5px; + border:1px solid #BFBFBF; +} +div#sqlalchemy-documentation a, div#sqlalchemy-documentation li { + padding:5px 0px; +} + +div#getting-started { + border-bottom:1px solid; +} + +div#sqlalchemy-documentation div#sqlalchemy-orm { + float:left; + width:48%; +} + +div#sqlalchemy-documentation div#sqlalchemy-core { + float:left; + width:48%; + margin:0; + padding-left:10px; + border-left:1px solid; +} + +div#dialect-documentation { + border-top:1px solid; + /*clear:left;*/ +} diff --git a/lib/mako-0.7.2/doc/_static/doctools.js b/lib/mako-0.7.2/doc/_static/doctools.js new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_static/doctools.js @@ -0,0 +1,247 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +} + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s == 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * small function to check if an array contains + * a given item. + */ +jQuery.contains = function(arr, item) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] == item) + return true; + } + return false; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node) { + if (node.nodeType == 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this); + }); + } + } + return this.each(function() { + highlight(this); + }); +}; + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated == 'undefined') + return string; + return (typeof translated == 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated == 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash && $.browser.mozilla) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) == 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this == '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); diff --git a/lib/mako-0.7.2/doc/_static/down-pressed.png b/lib/mako-0.7.2/doc/_static/down-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..6f7ad782782e4f8e39b0c6e15c7344700cdd2527 GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/down.png b/lib/mako-0.7.2/doc/_static/down.png new file mode 100644 index 0000000000000000000000000000000000000000..3003a88770de3977d47a2ba69893436a2860f9e7 GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/file.png b/lib/mako-0.7.2/doc/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..d18082e397e7e54f20721af768c4c2983258f1b4 GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/jquery.js b/lib/mako-0.7.2/doc/_static/jquery.js new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_static/jquery.js @@ -0,0 +1,154 @@ +/*! + * jQuery JavaScript Library v1.4.2 + * http://jquery.com/ + * + * Copyright 2010, John Resig + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * Copyright 2010, The Dojo Foundation + * Released under the MIT, BSD, and GPL Licenses. + * + * Date: Sat Feb 13 22:33:48 2010 -0500 + */ +(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/, +Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&& +(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this, +a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b=== +"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this, +function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b
a"; +var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected, +parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent= +false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n= +s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true, +applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando]; +else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this, +a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b=== +w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i, +cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected= +c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed"); +a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g, +function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split("."); +k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a), +C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B=0){a.type= +e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&& +f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive; +if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data", +e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a, +"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a, +d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g, +e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift(); +t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D|| +g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()}, +CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m, +g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)}, +text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}}, +setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return hl[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h= +h[3];l=0;for(m=h.length;l=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m=== +"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g, +h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&& +q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML=""; +if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="

";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}(); +(function(){var g=s.createElement("div");g.innerHTML="
";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}: +function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f0)for(var j=d;j0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j= +{},i;if(f&&a.length){e=0;for(var o=a.length;e-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a=== +"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode", +d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")? +a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType=== +1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/"},F={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div
","
"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d= +c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this}, +wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})}, +prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b, +this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild); +return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja, +""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]); +return this}else{e=0;for(var j=d.length;e0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["", +""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]===""&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e= +c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]? +c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja= +function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter= +Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a, +"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f= +a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b= +a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=//gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!== +"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("
").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this}, +serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "), +function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href, +global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&& +e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)? +"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache=== +false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B= +false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since", +c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E|| +d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x); +g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status=== +1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b=== +"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional; +if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration=== +"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]|| +c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start; +this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now= +this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem, +e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b
"; +a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b); +c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a, +d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top- +f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset": +"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in +e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window); diff --git a/lib/mako-0.7.2/doc/_static/makoLogo.png b/lib/mako-0.7.2/doc/_static/makoLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c43c087eb48ebfc2223b76cf3df2fa7868c2a72b GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/minus.png b/lib/mako-0.7.2/doc/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..da1c5620d10c047525a467a425abe9ff5269cfc2 GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/plus.png b/lib/mako-0.7.2/doc/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..b3cb37425ea68b39ffa7b2e5fb69161275a87541 GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/_static/pygments.css b/lib/mako-0.7.2/doc/_static/pygments.css new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_static/pygments.css @@ -0,0 +1,62 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #eeffcc; } +.highlight .c { color: #408090; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #007020; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #007020 } /* Comment.Preproc */ +.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #303030 } /* Generic.Output */ +.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #007020 } /* Keyword.Pseudo */ +.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #902000 } /* Keyword.Type */ +.highlight .m { color: #208050 } /* Literal.Number */ +.highlight .s { color: #4070a0 } /* Literal.String */ +.highlight .na { color: #4070a0 } /* Name.Attribute */ +.highlight .nb { color: #007020 } /* Name.Builtin */ +.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ +.highlight .no { color: #60add5 } /* Name.Constant */ +.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ +.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #007020 } /* Name.Exception */ +.highlight .nf { color: #06287e } /* Name.Function */ +.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ +.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #bb60d5 } /* Name.Variable */ +.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #208050 } /* Literal.Number.Float */ +.highlight .mh { color: #208050 } /* Literal.Number.Hex */ +.highlight .mi { color: #208050 } /* Literal.Number.Integer */ +.highlight .mo { color: #208050 } /* Literal.Number.Oct */ +.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ +.highlight .sc { color: #4070a0 } /* Literal.String.Char */ +.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4070a0 } /* Literal.String.Double */ +.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ +.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ +.highlight .sx { color: #c65d09 } /* Literal.String.Other */ +.highlight .sr { color: #235388 } /* Literal.String.Regex */ +.highlight .s1 { color: #4070a0 } /* Literal.String.Single */ +.highlight .ss { color: #517918 } /* Literal.String.Symbol */ +.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ +.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ +.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ +.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/lib/mako-0.7.2/doc/_static/searchtools.js b/lib/mako-0.7.2/doc/_static/searchtools.js new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/_static/searchtools.js @@ -0,0 +1,560 @@ +/* + * searchtools.js_t + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilties for the full-text search. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words, hlwords is the list of normal, unstemmed + * words. the first one is used to find the occurance, the + * latter for highlighting it. + */ + +jQuery.makeSearchSummary = function(text, keywords, hlwords) { + var textLower = text.toLowerCase(); + var start = 0; + $.each(keywords, function() { + var i = textLower.indexOf(this.toLowerCase()); + if (i > -1) + start = i; + }); + start = Math.max(start - 120, 0); + var excerpt = ((start > 0) ? '...' : '') + + $.trim(text.substr(start, 240)) + + ((start + 240 - text.length) ? '...' : ''); + var rv = $('
').text(excerpt); + $.each(hlwords, function() { + rv = rv.highlightText(this, 'highlighted'); + }); + return rv; +} + + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + + +/** + * Search Module + */ +var Search = { + + _index : null, + _queued_query : null, + _pulse_status : -1, + + init : function() { + var params = $.getQueryParameters(); + if (params.q) { + var query = params.q[0]; + $('input[name="q"]')[0].value = query; + this.performSearch(query); + } + }, + + loadIndex : function(url) { + $.ajax({type: "GET", url: url, data: null, success: null, + dataType: "script", cache: true}); + }, + + setIndex : function(index) { + var q; + this._index = index; + if ((q = this._queued_query) !== null) { + this._queued_query = null; + Search.query(q); + } + }, + + hasIndex : function() { + return this._index !== null; + }, + + deferQuery : function(query) { + this._queued_query = query; + }, + + stopPulse : function() { + this._pulse_status = 0; + }, + + startPulse : function() { + if (this._pulse_status >= 0) + return; + function pulse() { + Search._pulse_status = (Search._pulse_status + 1) % 4; + var dotString = ''; + for (var i = 0; i < Search._pulse_status; i++) + dotString += '.'; + Search.dots.text(dotString); + if (Search._pulse_status > -1) + window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something + */ + performSearch : function(query) { + // create the required interface elements + this.out = $('#search-results'); + this.title = $('

' + _('Searching') + '

').appendTo(this.out); + this.dots = $('').appendTo(this.title); + this.status = $('

').appendTo(this.out); + this.output = $('

'); + } + // Prettify the comment rating. + comment.pretty_rating = comment.rating + ' point' + + (comment.rating == 1 ? '' : 's'); + // Make a class (for displaying not yet moderated comments differently) + comment.css_class = comment.displayed ? '' : ' moderate'; + // Create a div for this comment. + var context = $.extend({}, opts, comment); + var div = $(renderTemplate(commentTemplate, context)); + + // If the user has voted on this comment, highlight the correct arrow. + if (comment.vote) { + var direction = (comment.vote == 1) ? 'u' : 'd'; + div.find('#' + direction + 'v' + comment.id).hide(); + div.find('#' + direction + 'u' + comment.id).show(); + } + + if (opts.moderator || comment.text != '[deleted]') { + div.find('a.reply').show(); + if (comment.proposal_diff) + div.find('#sp' + comment.id).show(); + if (opts.moderator && !comment.displayed) + div.find('#cm' + comment.id).show(); + if (opts.moderator || (opts.username == comment.username)) + div.find('#dc' + comment.id).show(); + } + return div; + } + + /** + * A simple template renderer. Placeholders such as <%id%> are replaced + * by context['id'] with items being escaped. Placeholders such as <#id#> + * are not escaped. + */ + function renderTemplate(template, context) { + var esc = $(document.createElement('div')); + + function handle(ph, escape) { + var cur = context; + $.each(ph.split('.'), function() { + cur = cur[this]; + }); + return escape ? esc.text(cur || "").html() : cur; + } + + return template.replace(/<([%#])([\w\.]*)\1>/g, function() { + return handle(arguments[2], arguments[1] == '%' ? true : false); + }); + } + + /** Flash an error message briefly. */ + function showError(message) { + $(document.createElement('div')).attr({'class': 'popup-error'}) + .append($(document.createElement('div')) + .attr({'class': 'error-message'}).text(message)) + .appendTo('body') + .fadeIn("slow") + .delay(2000) + .fadeOut("slow"); + } + + /** Add a link the user uses to open the comments popup. */ + $.fn.comment = function() { + return this.each(function() { + var id = $(this).attr('id').substring(1); + var count = COMMENT_METADATA[id]; + var title = count + ' comment' + (count == 1 ? '' : 's'); + var image = count > 0 ? opts.commentBrightImage : opts.commentImage; + var addcls = count == 0 ? ' nocomment' : ''; + $(this) + .append( + $(document.createElement('a')).attr({ + href: '#', + 'class': 'sphinx-comment-open' + addcls, + id: 'ao' + id + }) + .append($(document.createElement('img')).attr({ + src: image, + alt: 'comment', + title: title + })) + .click(function(event) { + event.preventDefault(); + show($(this).attr('id').substring(2)); + }) + ) + .append( + $(document.createElement('a')).attr({ + href: '#', + 'class': 'sphinx-comment-close hidden', + id: 'ah' + id + }) + .append($(document.createElement('img')).attr({ + src: opts.closeCommentImage, + alt: 'close', + title: 'close' + })) + .click(function(event) { + event.preventDefault(); + hide($(this).attr('id').substring(2)); + }) + ); + }); + }; + + var opts = { + processVoteURL: '/_process_vote', + addCommentURL: '/_add_comment', + getCommentsURL: '/_get_comments', + acceptCommentURL: '/_accept_comment', + deleteCommentURL: '/_delete_comment', + commentImage: '/static/_static/comment.png', + closeCommentImage: '/static/_static/comment-close.png', + loadingImage: '/static/_static/ajax-loader.gif', + commentBrightImage: '/static/_static/comment-bright.png', + upArrow: '/static/_static/up.png', + downArrow: '/static/_static/down.png', + upArrowPressed: '/static/_static/up-pressed.png', + downArrowPressed: '/static/_static/down-pressed.png', + voting: false, + moderator: false + }; + + if (typeof COMMENT_OPTIONS != "undefined") { + opts = jQuery.extend(opts, COMMENT_OPTIONS); + } + + var popupTemplate = '\ +
\ +

\ + Sort by:\ + best rated\ + newest\ + oldest\ +

\ +
Comments
\ +
\ + loading comments...
\ +
    \ +
    \ +

    Add a comment\ + (markup):

    \ +
    \ + reStructured text markup: *emph*, **strong**, \ + ``code``, \ + code blocks: :: and an indented block after blank line
    \ + \ + \ +

    \ + \ + Propose a change ▹\ + \ + \ + Propose a change ▿\ + \ +

    \ + \ + \ + \ + \ + \ +
    \ +
    '; + + var commentTemplate = '\ +
    \ +
    \ +
    \ + \ + \ + \ + \ + \ + \ +
    \ +
    \ + \ + \ + \ + \ + \ + \ +
    \ +
    \ +
    \ +

    \ + <%username%>\ + <%pretty_rating%>\ + <%time.delta%>\ +

    \ +
    <#text#>
    \ +

    \ + \ + reply ▿\ + proposal ▹\ + proposal ▿\ + \ + \ +

    \ +
    \
    +<#proposal_diff#>\
    +        
    \ +
      \ +
      \ +
      \ +
      \ + '; + + var replyTemplate = '\ +
    • \ +
      \ +
      \ + \ + \ + \ + \ + \ +
      \ +
      \ +
    • '; + + $(document).ready(function() { + init(); + }); +})(jQuery); + +$(document).ready(function() { + // add comment anchors for all paragraphs that are commentable + $('.sphinx-has-comment').comment(); + + // highlight search words in search results + $("div.context").each(function() { + var params = $.getQueryParameters(); + var terms = (params.q) ? params.q[0].split(/\s+/) : []; + var result = $(this); + $.each(terms, function() { + result.highlightText(this.toLowerCase(), 'highlighted'); + }); + }); + + // directly open comment window if requested + var anchor = document.location.hash; + if (anchor.substring(0, 9) == '#comment-') { + $('#ao' + anchor.substring(9)).click(); + document.location.hash = '#s' + anchor.substring(9); + } +}); diff --git a/lib/mako-0.7.2/doc/build/Makefile b/lib/mako-0.7.2/doc/build/Makefile new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/Makefile @@ -0,0 +1,137 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = output + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest dist-html site-mako + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dist-html same as html, but places files in /doc" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html -A mako_layout=html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dist-html: + $(SPHINXBUILD) -b html -A mako_layout=html $(ALLSPHINXOPTS) .. + @echo + @echo "Build finished. The HTML pages are in ../." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SQLAlchemy.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SQLAlchemy.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/SQLAlchemy" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SQLAlchemy" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + cp texinputs/* $(BUILDDIR)/latex/ + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) . + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/lib/mako-0.7.2/doc/build/builder/__init__.py b/lib/mako-0.7.2/doc/build/builder/__init__.py new file mode 100644 diff --git a/lib/mako-0.7.2/doc/build/builder/builders.py b/lib/mako-0.7.2/doc/build/builder/builders.py new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/builder/builders.py @@ -0,0 +1,97 @@ +from sphinx.application import TemplateBridge +from sphinx.builders.html import StandaloneHTMLBuilder +from sphinx.highlighting import PygmentsBridge +from sphinx.jinja2glue import BuiltinTemplateLoader +from pygments import highlight +from pygments.lexer import RegexLexer, bygroups, using +from pygments.token import * +from pygments.filter import Filter, apply_filters +from pygments.lexers import PythonLexer, PythonConsoleLexer +from pygments.formatters import HtmlFormatter, LatexFormatter +import re +import os +from mako.lookup import TemplateLookup +from mako.template import Template +from mako.ext.pygmentplugin import MakoLexer + +rtd = os.environ.get('READTHEDOCS', None) == 'True' + +class MakoBridge(TemplateBridge): + def init(self, builder, *args, **kw): + self.jinja2_fallback = BuiltinTemplateLoader() + self.jinja2_fallback.init(builder, *args, **kw) + + builder.config.html_context['site_base'] = builder.config['site_base'] + + self.lookup = TemplateLookup( + directories=builder.config.templates_path, + imports=[ + "from builder import util" + ] + ) + + def render(self, template, context): + template = template.replace(".html", ".mako") + context['prevtopic'] = context.pop('prev', None) + context['nexttopic'] = context.pop('next', None) + + # RTD layout + if rtd: + # add variables if not present, such + # as if local test of READTHEDOCS variable + if 'MEDIA_URL' not in context: + context['MEDIA_URL'] = "http://media.readthedocs.org/" + if 'slug' not in context: + context['slug'] = "mako-test-slug" + if 'url' not in context: + context['url'] = "/some/test/url" + if 'current_version' not in context: + context['current_version'] = "some_version" + if 'versions' not in context: + context['versions'] = [('default', '/default/')] + + context['docs_base'] = "http://readthedocs.org" + context['toolbar'] = True + context['layout'] = "rtd_layout.mako" + context['pdf_url'] = "%spdf/%s/%s/%s.pdf" % ( + context['MEDIA_URL'], + context['slug'], + context['current_version'], + context['slug'] + ) + # local docs layout + else: + context['toolbar'] = False + context['docs_base'] = "/" + context['layout'] = "layout.mako" + + context.setdefault('_', lambda x:x) + return self.lookup.get_template(template).render_unicode(**context) + + def render_string(self, template, context): + # this is used for .js, .css etc. and we don't have + # local copies of that stuff here so use the jinja render. + return self.jinja2_fallback.render_string(template, context) + +class StripDocTestFilter(Filter): + def filter(self, lexer, stream): + for ttype, value in stream: + if ttype is Token.Comment and re.match(r'#\s*doctest:', value): + continue + yield ttype, value + + +def autodoc_skip_member(app, what, name, obj, skip, options): + if what == 'class' and skip and name == '__init__': + return False + else: + return skip + +def setup(app): +# app.connect('autodoc-skip-member', autodoc_skip_member) + # Mako is already in Pygments, adding the local + # lexer here so that the latest syntax is available + app.add_lexer('mako', MakoLexer()) + app.add_config_value('site_base', "", True) + + \ No newline at end of file diff --git a/lib/mako-0.7.2/doc/build/builder/util.py b/lib/mako-0.7.2/doc/build/builder/util.py new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/builder/util.py @@ -0,0 +1,12 @@ +import re + +def striptags(text): + return re.compile(r'<[^>]*>').sub('', text) + +def go(m): + # .html with no anchor if present, otherwise "#" for top of page + return m.group(1) or '#' + +def strip_toplevel_anchors(text): + return re.compile(r'(\.html)?#[-\w]+-toplevel').sub(go, text) + diff --git a/lib/mako-0.7.2/doc/build/caching.rst b/lib/mako-0.7.2/doc/build/caching.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/caching.rst @@ -0,0 +1,393 @@ +.. _caching_toplevel: + +======= +Caching +======= + +Any template or component can be cached using the ``cache`` +argument to the ``<%page>``, ``<%def>`` or ``<%block>`` directives: + +.. sourcecode:: mako + + <%page cached="True"/> + + template text + +The above template, after being executed the first time, will +store its content within a cache that by default is scoped +within memory. Subsequent calls to the template's :meth:`~.Template.render` +method will return content directly from the cache. When the +:class:`.Template` object itself falls out of scope, its corresponding +cache is garbage collected along with the template. + +By default, caching requires that the `Beaker `_ package be installed on the +system, however the mechanism of caching can be customized to use +any third party or user defined system -- see :ref:`cache_plugins`. + +In addition to being available on the ``<%page>`` tag, the caching flag and all +its options can be used with the ``<%def>`` tag as well: + +.. sourcecode:: mako + + <%def name="mycomp" cached="True" cache_timeout="60"> + other text + + +... and equivalently with the ``<%block>`` tag, anonymous or named: + +.. sourcecode:: mako + + <%block cached="True" cache_timeout="60"> + other text + + +Cache Arguments +=============== + +Mako has two cache arguments available on tags that are +available in all cases. The rest of the arguments +available are specific to a backend. + +The two generic tags arguments are: + +* ``cached="True"`` - enable caching for this ``<%page>``, + ``<%def>``, or ``<%block>``. +* ``cache_key`` - the "key" used to uniquely identify this content + in the cache. Usually, this key is chosen automatically + based on the name of the rendering callable (i.e. ``body`` + when used in ``<%page>``, the name of the def when using ``<%def>``, + the explicit or internally-generated name when using ``<%block>``). + Using the ``cache_key`` parameter, the key can be overridden + using a fixed or programmatically generated value. + + For example, here's a page + that caches any page which inherits from it, based on the + filename of the calling template: + + .. sourcecode:: mako + + <%page cached="True" cache_key="${self.filename}"/> + + ${next.body()} + + ## rest of template + +On a :class:`.Template` or :class:`.TemplateLookup`, the +caching can be configured using these arguments: + +* ``cache_enabled`` - Setting this + to ``False`` will disable all caching functionality + when the template renders. Defaults to ``True``. + e.g.: + + .. sourcecode:: python + + lookup = TemplateLookup( + directories='/path/to/templates', + cache_enabled = False + ) + +* ``cache_impl`` - The string name of the cache backend + to use. This defaults to ``'beaker'``, which has historically + been the only cache backend supported by Mako. + + .. versionadded:: 0.6.0 + + For example, here's how to use the upcoming + `dogpile.cache `_ + backend: + + .. sourcecode:: python + + lookup = TemplateLookup( + directories='/path/to/templates', + cache_impl = 'dogpile.cache', + cache_args = {'regions':my_dogpile_regions} + ) + +* ``cache_args`` - A dictionary of cache parameters that + will be consumed by the cache backend. See + :ref:`beaker_backend` for examples. + + .. versionadded:: 0.6.0 + +Backend-Specific Cache Arguments +-------------------------------- + +The ``<%page>``, ``<%def>``, and ``<%block>`` tags +accept any named argument that starts with the prefix ``"cache_"``. +Those arguments are then packaged up and passed along to the +underlying caching implementation, minus the ``"cache_"`` prefix. + +The actual arguments understood are determined by the backend. + +* :ref:`beaker_backend` - Includes arguments understood by + Beaker. +* :ref:`dogpile.cache_backend` - Includes arguments understood by + dogpile.cache. + +.. _beaker_backend: + +Using the Beaker Cache Backend +------------------------------ + +When using Beaker, new implementations will want to make usage +of **cache regions** so that cache configurations can be maintained +externally to templates. These configurations live under +named "regions" that can be referred to within templates themselves. + +.. versionadded:: 0.6.0 + Support for Beaker cache regions. + +For example, suppose we would like two regions. One is a "short term" +region that will store content in a memory-based dictionary, +expiring after 60 seconds. The other is a Memcached region, +where values should expire in five minutes. To configure +our :class:`.TemplateLookup`, first we get a handle to a +:class:`beaker.cache.CacheManager`: + +.. sourcecode:: python + + from beaker.cache import CacheManager + + manager = CacheManager(cache_regions={ + 'short_term':{ + 'type': 'memory', + 'expire': 60 + }, + 'long_term':{ + 'type': 'ext:memcached', + 'url': '127.0.0.1:11211', + 'expire': 300 + } + }) + + lookup = TemplateLookup( + directories=['/path/to/templates'], + module_directory='/path/to/modules', + cache_impl='beaker', + cache_args={ + 'manager':manager + } + ) + +Our templates can then opt to cache data in one of either region, +using the ``cache_region`` argument. Such as using ``short_term`` +at the ``<%page>`` level: + +.. sourcecode:: mako + + <%page cached="True" cache_region="short_term"> + + ## ... + +Or, ``long_term`` at the ``<%block>`` level: + +.. sourcecode:: mako + + <%block name="header" cached="True" cache_region="long_term"> + other text + + +The Beaker backend also works without regions. There are a +variety of arguments that can be passed to the ``cache_args`` +dictionary, which are also allowable in templates via the +``<%page>``, ``<%block>``, +and ``<%def>`` tags specific to those sections. The values +given override those specified at the :class:`.TemplateLookup` +or :class:`.Template` level. + +With the possible exception +of ``cache_timeout``, these arguments are probably better off +staying at the template configuration level. Each argument +specified as ``cache_XYZ`` in a template tag is specified +without the ``cache_`` prefix in the ``cache_args`` dictionary: + +* ``cache_timeout`` - number of seconds in which to invalidate the + cached data. After this timeout, the content is re-generated + on the next call. Available as ``timeout`` in the ``cache_args`` + dictionary. +* ``cache_type`` - type of caching. ``'memory'``, ``'file'``, ``'dbm'``, or + ``'ext:memcached'`` (note that the string ``memcached`` is + also accepted by the dogpile.cache Mako plugin, though not by Beaker itself). + Available as ``type`` in the ``cache_args`` dictionary. +* ``cache_url`` - (only used for ``memcached`` but required) a single + IP address or a semi-colon separated list of IP address of + memcache servers to use. Available as ``url`` in the ``cache_args`` + dictionary. +* ``cache_dir`` - in the case of the ``'file'`` and ``'dbm'`` cache types, + this is the filesystem directory with which to store data + files. If this option is not present, the value of + ``module_directory`` is used (i.e. the directory where compiled + template modules are stored). If neither option is available + an exception is thrown. Available as ``dir`` in the + ``cache_args`` dictionary. + +.. _dogpile.cache_backend: + +Using the dogpile.cache Backend +------------------------------- + +`dogpile.cache`_ is a new replacement for Beaker. It provides +a modernized, slimmed down interface and is generally easier to use +than Beaker. As of this writing it has not yet been released. dogpile.cache +includes its own Mako cache plugin -- see :mod:`dogpile.cache.plugins.mako_cache` in the +dogpile.cache documentation. + +Programmatic Cache Access +========================= + +The :class:`.Template`, as well as any template-derived :class:`.Namespace`, has +an accessor called ``cache`` which returns the :class:`.Cache` object +for that template. This object is a facade on top of the underlying +:class:`.CacheImpl` object, and provides some very rudimental +capabilities, such as the ability to get and put arbitrary +values: + +.. sourcecode:: mako + + <% + local.cache.set("somekey", type="memory", "somevalue") + %> + +Above, the cache associated with the ``local`` namespace is +accessed and a key is placed within a memory cache. + +More commonly, the ``cache`` object is used to invalidate cached +sections programmatically: + +.. sourcecode:: python + + template = lookup.get_template('/sometemplate.html') + + # invalidate the "body" of the template + template.cache.invalidate_body() + + # invalidate an individual def + template.cache.invalidate_def('somedef') + + # invalidate an arbitrary key + template.cache.invalidate('somekey') + +You can access any special method or attribute of the :class:`.CacheImpl` +itself using the :attr:`impl <.Cache.impl>` attribute: + +.. sourcecode:: python + + template.cache.impl.do_something_special() + +Note that using implementation-specific methods will mean you can't +swap in a different kind of :class:`.CacheImpl` implementation at a +later time. + +.. _cache_plugins: + +Cache Plugins +============= + +The mechanism used by caching can be plugged in +using a :class:`.CacheImpl` subclass. This class implements +the rudimental methods Mako needs to implement the caching +API. Mako includes the :class:`.BeakerCacheImpl` class to +provide the default implementation. A :class:`.CacheImpl` class +is acquired by Mako using a ``pkg_resources`` entrypoint, using +the name given as the ``cache_impl`` argument to :class:`.Template` +or :class:`.TemplateLookup`. This entry point can be +installed via the standard `setuptools`/``setup()`` procedure, underneath +the `EntryPoint` group named ``"mako.cache"``. It can also be +installed at runtime via a convenience installer :func:`.register_plugin` +which accomplishes essentially the same task. + +An example plugin that implements a local dictionary cache: + +.. sourcecode:: python + + from mako.cache import Cacheimpl, register_plugin + + class SimpleCacheImpl(CacheImpl): + def __init__(self, cache): + super(SimpleCacheImpl, self).__init__(cache) + self._cache = {} + + def get_or_create(self, key, creation_function, **kw): + if key in self._cache: + return self._cache[key] + else: + self._cache[key] = value = creation_function() + return value + + def set(self, key, value, **kwargs): + self._cache[key] = value + + def get(self, key, **kwargs): + return self._cache.get(key) + + def invalidate(self, key, **kwargs): + self._cache.pop(key, None) + + # optional - register the class locally + register_plugin("simple", __name__, "SimpleCacheImpl") + +Enabling the above plugin in a template would look like: + +.. sourcecode:: python + + t = Template("mytemplate", + file="mytemplate.html", + cache_impl='simple') + +Guidelines for Writing Cache Plugins +------------------------------------ + +* The :class:`.CacheImpl` is created on a per-:class:`.Template` basis. The + class should ensure that only data for the parent :class:`.Template` is + persisted or returned by the cache methods. The actual :class:`.Template` + is available via the ``self.cache.template`` attribute. The ``self.cache.id`` + attribute, which is essentially the unique modulename of the template, is + a good value to use in order to represent a unique namespace of keys specific + to the template. +* Templates only use the :meth:`.CacheImpl.get_or_create()` method + in an implicit fashion. The :meth:`.CacheImpl.set`, + :meth:`.CacheImpl.get`, and :meth:`.CacheImpl.invalidate` methods are + only used in response to direct programmatic access to the corresponding + methods on the :class:`.Cache` object. +* :class:`.CacheImpl` will be accessed in a multithreaded fashion if the + :class:`.Template` itself is used multithreaded. Care should be taken + to ensure caching implementations are threadsafe. +* A library like `Dogpile `_, which + is a minimal locking system derived from Beaker, can be used to help + implement the :meth:`.CacheImpl.get_or_create` method in a threadsafe + way that can maximize effectiveness across multiple threads as well + as processes. :meth:`.CacheImpl.get_or_create` is the + key method used by templates. +* All arguments passed to ``**kw`` come directly from the parameters + inside the ``<%def>``, ``<%block>``, or ``<%page>`` tags directly, + minus the ``"cache_"`` prefix, as strings, with the exception of + the argument ``cache_timeout``, which is passed to the plugin + as the name ``timeout`` with the value converted to an integer. + Arguments present in ``cache_args`` on :class:`.Template` or + :class:`.TemplateLookup` are passed directly, but are superseded + by those present in the most specific template tag. +* The directory where :class:`.Template` places module files can + be acquired using the accessor ``self.cache.template.module_directory``. + This directory can be a good place to throw cache-related work + files, underneath a prefix like ``_my_cache_work`` so that name + conflicts with generated modules don't occur. + +API Reference +============= + +.. autoclass:: mako.cache.Cache + :members: + :show-inheritance: + +.. autoclass:: mako.cache.CacheImpl + :members: + :show-inheritance: + +.. autofunction:: mako.cache.register_plugin + +.. autoclass:: mako.ext.beaker_cache.BeakerCacheImpl + :members: + :show-inheritance: + diff --git a/lib/mako-0.7.2/doc/build/conf.py b/lib/mako-0.7.2/doc/build/conf.py new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/conf.py @@ -0,0 +1,287 @@ +# -*- coding: utf-8 -*- +# +# Mako documentation build configuration file +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +sys.path.insert(0, os.path.abspath('../..')) +sys.path.insert(0, os.path.abspath('.')) + +import mako + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', +# 'sphinx.ext.doctest', 'builder.builders'] + +extensions = ['sphinx.ext.autodoc','sphinx.ext.intersphinx', + 'sphinx.ext.doctest', 'builder.builders'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['templates'] + +nitpicky = True + +site_base = "http://www.makotemplates.org" + +# The suffix of source filenames. +source_suffix = '.rst' + +template_bridge = "builder.builders.MakoBridge" + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Mako' +copyright = u'the Mako authors and contributors' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = mako.__version__ +# The full version, including alpha/beta/rc tags. +release = mako.__version__ + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The style sheet to use for HTML and HTML Help pages. A file of that name +# must exist either in Sphinx' static/ path, or in one of the custom paths +# given in html_static_path. +html_style = 'default.css' + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +html_title = "%s %s Documentation" % (project, release) + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +html_last_updated_fmt = '%m/%d/%Y %H:%M:%S' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +html_domain_indices = False + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, the reST sources are included in the HTML build as _sources/. +#html_copy_source = True + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Makodoc' + +#autoclass_content = 'both' + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'mako_%s.tex' % release.replace('.', '_'), ur'Mako Documentation', + ur'Mike Bayer', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +# sets TOC depth to 2. +latex_preamble = '\setcounter{tocdepth}{3}' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + +#latex_elements = { +# 'papersize': 'letterpaper', +# 'pointsize': '10pt', +#} + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'mako', u'Mako Documentation', + [u'Mako authors'], 1) +] + + +# -- Options for Epub output --------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = u'Mako' +epub_author = u'Mako authors' +epub_publisher = u'Mako authors' +epub_copyright = u'Mako authors' + +# The language of the text. It defaults to the language option +# or en if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +#epub_exclude_files = [] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True + +intersphinx_mapping = { + 'dogpilecache':('http://dogpilecache.readthedocs.org/en/latest', None), + 'beaker':('http://beaker.readthedocs.org/en/latest',None), +} diff --git a/lib/mako-0.7.2/doc/build/defs.rst b/lib/mako-0.7.2/doc/build/defs.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/defs.rst @@ -0,0 +1,622 @@ +.. _defs_toplevel: + +=============== +Defs and Blocks +=============== + +``<%def>`` and ``<%block>`` are two tags that both demarcate any block of text +and/or code. They both exist within generated Python as a callable function, +i.e., a Python ``def``. They differ in their scope and calling semantics. +Whereas ``<%def>`` provides a construct that is very much like a named Python +``def``, the ``<%block>`` is more layout oriented. + +Using Defs +========== + +The ``<%def>`` tag requires a ``name`` attribute, where the ``name`` references +a Python function signature: + +.. sourcecode:: mako + + <%def name="hello()"> + hello world + + +To invoke the ``<%def>``, it is normally called as an expression: + +.. sourcecode:: mako + + the def: ${hello()} + +If the ``<%def>`` is not nested inside of another ``<%def>``, +it's known as a **top level def** and can be accessed anywhere in +the template, including above where it was defined. + +All defs, top level or not, have access to the current +contextual namespace in exactly the same way their containing +template does. Suppose the template below is executed with the +variables ``username`` and ``accountdata`` inside the context: + +.. sourcecode:: mako + + Hello there ${username}, how are ya. Lets see what your account says: + + ${account()} + + <%def name="account()"> + Account for ${username}:
      + + % for row in accountdata: + Value: ${row}
      + % endfor + + +The ``username`` and ``accountdata`` variables are present +within the main template body as well as the body of the +``account()`` def. + +Since defs are just Python functions, you can define and pass +arguments to them as well: + +.. sourcecode:: mako + + ${account(accountname='john')} + + <%def name="account(accountname, type='regular')"> + account name: ${accountname}, type: ${type} + + +When you declare an argument signature for your def, they are +required to follow normal Python conventions (i.e., all +arguments are required except keyword arguments with a default +value). This is in contrast to using context-level variables, +which evaluate to ``UNDEFINED`` if you reference a name that +does not exist. + +Calling Defs from Other Files +----------------------------- + +Top level ``<%def>``\ s are **exported** by your template's +module, and can be called from the outside; including from other +templates, as well as normal Python code. Calling a ``<%def>`` +from another template is something like using an ``<%include>`` +-- except you are calling a specific function within the +template, not the whole template. + +The remote ``<%def>`` call is also a little bit like calling +functions from other modules in Python. There is an "import" +step to pull the names from another template into your own +template; then the function or functions are available. + +To import another template, use the ``<%namespace>`` tag: + +.. sourcecode:: mako + + <%namespace name="mystuff" file="mystuff.html"/> + +The above tag adds a local variable ``mystuff`` to the current +scope. + +Then, just call the defs off of ``mystuff``: + +.. sourcecode:: mako + + ${mystuff.somedef(x=5,y=7)} + +The ``<%namespace>`` tag also supports some of the other +semantics of Python's ``import`` statement, including pulling +names into the local variable space, or using ``*`` to represent +all names, using the ``import`` attribute: + +.. sourcecode:: mako + + <%namespace file="mystuff.html" import="foo, bar"/> + +This is just a quick intro to the concept of a **namespace**, +which is a central Mako concept that has its own chapter in +these docs. For more detail and examples, see +:ref:`namespaces_toplevel`. + +Calling Defs Programmatically +----------------------------- + +You can call defs programmatically from any :class:`.Template` object +using the :meth:`~.Template.get_def()` method, which returns a :class:`.DefTemplate` +object. This is a :class:`.Template` subclass which the parent +:class:`.Template` creates, and is usable like any other template: + +.. sourcecode:: python + + from mako.template import Template + + template = Template(""" + <%def name="hi(name)"> + hi ${name}! + + + <%def name="bye(name)"> + bye ${name}! + + """) + + print template.get_def("hi").render(name="ed") + print template.get_def("bye").render(name="ed") + +Defs within Defs +---------------- + +The def model follows regular Python rules for closures. +Declaring ``<%def>`` inside another ``<%def>`` declares it +within the parent's **enclosing scope**: + +.. sourcecode:: mako + + <%def name="mydef()"> + <%def name="subdef()"> + a sub def + + + i'm the def, and the subcomponent is ${subdef()} + + +Just like Python, names that exist outside the inner ``<%def>`` +exist inside it as well: + +.. sourcecode:: mako + + <% + x = 12 + %> + <%def name="outer()"> + <% + y = 15 + %> + <%def name="inner()"> + inner, x is ${x}, y is ${y} + + + outer, x is ${x}, y is ${y} + + +Assigning to a name inside of a def declares that name as local +to the scope of that def (again, like Python itself). This means +the following code will raise an error: + +.. sourcecode:: mako + + <% + x = 10 + %> + <%def name="somedef()"> + ## error ! + somedef, x is ${x} + <% + x = 27 + %> + + +...because the assignment to ``x`` declares ``x`` as local to the +scope of ``somedef``, rendering the "outer" version unreachable +in the expression that tries to render it. + +.. _defs_with_content: + +Calling a Def with Embedded Content and/or Other Defs +----------------------------------------------------- + +A flip-side to def within def is a def call with content. This +is where you call a def, and at the same time declare a block of +content (or multiple blocks) that can be used by the def being +called. The main point of such a call is to create custom, +nestable tags, just like any other template language's +custom-tag creation system -- where the external tag controls the +execution of the nested tags and can communicate state to them. +Only with Mako, you don't have to use any external Python +modules, you can define arbitrarily nestable tags right in your +templates. + +To achieve this, the target def is invoked using the form +``<%namepacename:defname>`` instead of the normal ``${}`` +syntax. This syntax, introduced in Mako 0.2.3, is functionally +equivalent to another tag known as ``%call``, which takes the form +``<%call expr='namespacename.defname(args)'>``. While ``%call`` +is available in all versions of Mako, the newer style is +probably more familiar looking. The ``namespace`` portion of the +call is the name of the **namespace** in which the def is +defined -- in the most simple cases, this can be ``local`` or +``self`` to reference the current template's namespace (the +difference between ``local`` and ``self`` is one of inheritance +-- see :ref:`namespaces_builtin` for details). + +When the target def is invoked, a variable ``caller`` is placed +in its context which contains another namespace containing the +body and other defs defined by the caller. The body itself is +referenced by the method ``body()``. Below, we build a ``%def`` +that operates upon ``caller.body()`` to invoke the body of the +custom tag: + +.. sourcecode:: mako + + <%def name="buildtable()"> + + +
      + ${caller.body()} +
      + + + <%self:buildtable> + I am the table body. + + +This produces the output (whitespace formatted): + +.. sourcecode:: html + + + +
      + I am the table body. +
      + +Using the older ``%call`` syntax looks like: + +.. sourcecode:: mako + + <%def name="buildtable()"> + + +
      + ${caller.body()} +
      + + + <%call expr="buildtable()"> + I am the table body. + + +The ``body()`` can be executed multiple times or not at all. +This means you can use def-call-with-content to build iterators, +conditionals, etc: + +.. sourcecode:: mako + + <%def name="lister(count)"> + % for x in range(count): + ${caller.body()} + % endfor + + + <%self:lister count="${3}"> + hi + + +Produces: + +.. sourcecode:: html + + hi + hi + hi + +Notice above we pass ``3`` as a Python expression, so that it +remains as an integer. + +A custom "conditional" tag: + +.. sourcecode:: mako + + <%def name="conditional(expression)"> + % if expression: + ${caller.body()} + % endif + + + <%self:conditional expression="${4==4}"> + i'm the result + + +Produces: + +.. sourcecode:: html + + i'm the result + +But that's not all. The ``body()`` function also can handle +arguments, which will augment the local namespace of the body +callable. The caller must define the arguments which it expects +to receive from its target def using the ``args`` attribute, +which is a comma-separated list of argument names. Below, our +``<%def>`` calls the ``body()`` of its caller, passing in an +element of data from its argument: + +.. sourcecode:: mako + + <%def name="layoutdata(somedata)"> + + % for item in somedata: + + % for col in item: + + % endfor + + % endfor +
      ${caller.body(col=col)}
      + + + <%self:layoutdata somedata="${[[1,2,3],[4,5,6],[7,8,9]]}" args="col">\ + Body data: ${col}\ + + +Produces: + +.. sourcecode:: html + + + + + + + + + + + + + + + + + +
      Body data: 1Body data: 2Body data: 3
      Body data: 4Body data: 5Body data: 6
      Body data: 7Body data: 8Body data: 9
      + +You don't have to stick to calling just the ``body()`` function. +The caller can define any number of callables, allowing the +``<%call>`` tag to produce whole layouts: + +.. sourcecode:: mako + + <%def name="layout()"> + ## a layout def +
      +
      + ${caller.header()} +
      + + + +
      + ${caller.body()} +
      +
      + + + ## calls the layout def + <%self:layout> + <%def name="header()"> + I am the header + + <%def name="sidebar()"> +
        +
      • sidebar 1
      • +
      • sidebar 2
      • +
      + + + this is the body + + +The above layout would produce: + +.. sourcecode:: html + +
      +
      + I am the header +
      + + + +
      + this is the body +
      +
      + +The number of things you can do with ``<%call>`` and/or the +``<%namespacename:defname>`` calling syntax is enormous. You can +create form widget libraries, such as an enclosing ``
      `` +tag and nested HTML input elements, or portable wrapping schemes +using ``
      `` or other elements. You can create tags that +interpret rows of data, such as from a database, providing the +individual columns of each row to a ``body()`` callable which +lays out the row any way it wants. Basically anything you'd do +with a "custom tag" or tag library in some other system, Mako +provides via ``<%def>`` tags and plain Python callables which are +invoked via ``<%namespacename:defname>`` or ``<%call>``. + +.. _blocks: + +Using Blocks +============ + +The ``<%block>`` tag introduces some new twists on the +``<%def>`` tag which make it more closely tailored towards layout. + +.. versionadded:: 0.4.1 + +An example of a block: + +.. sourcecode:: mako + + + + <%block> + this is a block. + + + + +In the above example, we define a simple block. The block renders its content in the place +that it's defined. Since the block is called for us, it doesn't need a name and the above +is referred to as an **anonymous block**. So the output of the above template will be: + +.. sourcecode:: html + + + + this is a block. + + + +So in fact the above block has absolutely no effect. Its usefulness comes when we start +using modifiers. Such as, we can apply a filter to our block: + +.. sourcecode:: mako + + + + <%block filter="h"> + this is some escaped html. + + + + +or perhaps a caching directive: + +.. sourcecode:: mako + + + + <%block cached="True" cache_timeout="60"> + This content will be cached for 60 seconds. + + + + +Blocks also work in iterations, conditionals, just like defs: + +.. sourcecode:: mako + + % if some_condition: + <%block>condition is met + % endif + +While the block renders at the point it is defined in the template, +the underlying function is present in the generated Python code only +once, so there's no issue with placing a block inside of a loop or +similar. Anonymous blocks are defined as closures in the local +rendering body, so have access to local variable scope: + +.. sourcecode:: mako + + % for i in range(1, 4): + <%block>i is ${i} + % endfor + +Using Named Blocks +------------------ + +Possibly the more important area where blocks are useful is when we +do actually give them names. Named blocks are tailored to behave +somewhat closely to Jinja2's block tag, in that they define an area +of a layout which can be overridden by an inheriting template. In +sharp contrast to the ``<%def>`` tag, the name given to a block is +global for the entire template regardless of how deeply it's nested: + +.. sourcecode:: mako + + + <%block name="header"> + + + <%block name="title">Title</%block> + + + + + ${next.body()} + + + +The above example has two named blocks "``header``" and "``title``", both of which can be referred to +by an inheriting template. A detailed walkthrough of this usage can be found at :ref:`inheritance_toplevel`. + +Note above that named blocks don't have any argument declaration the way defs do. They still implement themselves +as Python functions, however, so they can be invoked additional times beyond their initial definition: + +.. sourcecode:: mako + +
      + <%block name="pagecontrol"> + previous page | + next page + + + + ## some content +
      + + ${pagecontrol()} +
      + +The content referenced by ``pagecontrol`` above will be rendered both above and below the ```` tags. + +To keep things sane, named blocks have restrictions that defs do not: + +* The ``<%block>`` declaration cannot have any argument signature. +* The name of a ``<%block>`` can only be defined once in a template -- an error is raised if two blocks of the same + name occur anywhere in a single template, regardless of nesting. A similar error is raised if a top level def + shares the same name as that of a block. +* A named ``<%block>`` cannot be defined within a ``<%def>``, or inside the body of a "call", i.e. + ``<%call>`` or ``<%namespacename:defname>`` tag. Anonymous blocks can, however. + +Using Page Arguments in Named Blocks +------------------------------------ + +A named block is very much like a top level def. It has a similar +restriction to these types of defs in that arguments passed to the +template via the ``<%page>`` tag aren't automatically available. +Using arguments with the ``<%page>`` tag is described in the section +:ref:`namespaces_body`, and refers to scenarios such as when the +``body()`` method of a template is called from an inherited template passing +arguments, or the template is invoked from an ``<%include>`` tag +with arguments. To allow a named block to share the same arguments +passed to the page, the ``args`` attribute can be used: + +.. sourcecode:: mako + + <%page args="post"/> + + + + + <%block name="post_prose" args="post"> + ${post.content} + + + +Where above, if the template is called via a directive like +``<%include file="post.mako" args="post=post" />``, the ``post`` +variable is available both in the main body as well as the +``post_prose`` block. + +Similarly, the ``**pageargs`` variable is present, in named blocks only, +for those arguments not explicit in the ``<%page>`` tag: + +.. sourcecode:: mako + + <%block name="post_prose"> + ${pageargs['post'].content} + + +The ``args`` attribute is only allowed with named blocks. With +anonymous blocks, the Python function is always rendered in the same +scope as the call itself, so anything available directly outside the +anonymous block is available inside as well. diff --git a/lib/mako-0.7.2/doc/build/filtering.rst b/lib/mako-0.7.2/doc/build/filtering.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/filtering.rst @@ -0,0 +1,344 @@ +.. _filtering_toplevel: + +======================= +Filtering and Buffering +======================= + +Expression Filtering +==================== + +As described in the chapter :ref:`syntax_toplevel`, the "``|``" operator can be +applied to a "``${}``" expression to apply escape filters to the +output: + +.. sourcecode:: mako + + ${"this is some text" | u} + +The above expression applies URL escaping to the expression, and +produces ``this+is+some+text``. + +The built-in escape flags are: + +* ``u`` : URL escaping, provided by + ``urllib.quote_plus(string.encode('utf-8'))`` +* ``h`` : HTML escaping, provided by + ``markupsafe.escape(string)`` + + .. versionadded:: 0.3.4 + Prior versions use ``cgi.escape(string, True)``. + +* ``x`` : XML escaping +* ``trim`` : whitespace trimming, provided by ``string.strip()`` +* ``entity`` : produces HTML entity references for applicable + strings, derived from ``htmlentitydefs`` +* ``unicode`` (``str`` on Python 3): produces a Python unicode + string (this function is applied by default) +* ``decode.``: decode input into a Python + unicode with the specified encoding +* ``n`` : disable all default filtering; only filters specified + in the local expression tag will be applied. + +To apply more than one filter, separate them by a comma: + +.. sourcecode:: mako + + ${" some value " | h,trim} + +The above produces ``<tag>some value</tag>``, with +no leading or trailing whitespace. The HTML escaping function is +applied first, the "trim" function second. + +Naturally, you can make your own filters too. A filter is just a +Python function that accepts a single string argument, and +returns the filtered result. The expressions after the ``|`` +operator draw upon the local namespace of the template in which +they appear, meaning you can define escaping functions locally: + +.. sourcecode:: mako + + <%! + def myescape(text): + return "" + text + "" + %> + + Here's some tagged text: ${"text" | myescape} + +Or from any Python module: + +.. sourcecode:: mako + + <%! + import myfilters + %> + + Here's some tagged text: ${"text" | myfilters.tagfilter} + +A page can apply a default set of filters to all expression tags +using the ``expression_filter`` argument to the ``%page`` tag: + +.. sourcecode:: mako + + <%page expression_filter="h"/> + + Escaped text: ${"some html"} + +Result: + +.. sourcecode:: html + + Escaped text: <html>some html</html> + +.. _filtering_default_filters: + +The ``default_filters`` Argument +-------------------------------- + +In addition to the ``expression_filter`` argument, the +``default_filters`` argument to both :class:`.Template` and +:class:`.TemplateLookup` can specify filtering for all expression tags +at the programmatic level. This array-based argument, when given +its default argument of ``None``, will be internally set to +``["unicode"]`` (or ``["str"]`` on Python 3), except when +``disable_unicode=True`` is set in which case it defaults to +``["str"]``: + +.. sourcecode:: python + + t = TemplateLookup(directories=['/tmp'], default_filters=['unicode']) + +To replace the usual ``unicode``/``str`` function with a +specific encoding, the ``decode`` filter can be substituted: + +.. sourcecode:: python + + t = TemplateLookup(directories=['/tmp'], default_filters=['decode.utf8']) + +To disable ``default_filters`` entirely, set it to an empty +list: + +.. sourcecode:: python + + t = TemplateLookup(directories=['/tmp'], default_filters=[]) + +Any string name can be added to ``default_filters`` where it +will be added to all expressions as a filter. The filters are +applied from left to right, meaning the leftmost filter is +applied first. + +.. sourcecode:: python + + t = Template(templatetext, default_filters=['unicode', 'myfilter']) + +To ease the usage of ``default_filters`` with custom filters, +you can also add imports (or other code) to all templates using +the ``imports`` argument: + +.. sourcecode:: python + + t = TemplateLookup(directories=['/tmp'], + default_filters=['unicode', 'myfilter'], + imports=['from mypackage import myfilter']) + +The above will generate templates something like this: + +.. sourcecode:: python + + # .... + from mypackage import myfilter + + def render_body(context): + context.write(myfilter(unicode("some text"))) + +Turning off Filtering with the ``n`` Filter +------------------------------------------- + +In all cases the special ``n`` filter, used locally within an +expression, will **disable** all filters declared in the +``<%page>`` tag as well as in ``default_filters``. Such as: + +.. sourcecode:: mako + + ${'myexpression' | n} + +will render ``myexpression`` with no filtering of any kind, and: + +.. sourcecode:: mako + + ${'myexpression' | n,trim} + +will render ``myexpression`` using the ``trim`` filter only. + +Filtering Defs and Blocks +========================= + +The ``%def`` and ``%block`` tags have an argument called ``filter`` which will apply the +given list of filter functions to the output of the ``%def``: + +.. sourcecode:: mako + + <%def name="foo()" filter="h, trim"> + this is bold + + +When the ``filter`` attribute is applied to a def as above, the def +is automatically **buffered** as well. This is described next. + +Buffering +========= + +One of Mako's central design goals is speed. To this end, all of +the textual content within a template and its various callables +is by default piped directly to the single buffer that is stored +within the :class:`.Context` object. While this normally is easy to +miss, it has certain side effects. The main one is that when you +call a def using the normal expression syntax, i.e. +``${somedef()}``, it may appear that the return value of the +function is the content it produced, which is then delivered to +your template just like any other expression substitution, +except that normally, this is not the case; the return value of +``${somedef()}`` is simply the empty string ``''``. By the time +you receive this empty string, the output of ``somedef()`` has +been sent to the underlying buffer. + +You may not want this effect, if for example you are doing +something like this: + +.. sourcecode:: mako + + ${" results " + somedef() + " more results "} + +If the ``somedef()`` function produced the content "``somedef's +results``", the above template would produce this output: + +.. sourcecode:: html + + somedef's results results more results + +This is because ``somedef()`` fully executes before the +expression returns the results of its concatenation; the +concatenation in turn receives just the empty string as its +middle expression. + +Mako provides two ways to work around this. One is by applying +buffering to the ``%def`` itself: + +.. sourcecode:: mako + + <%def name="somedef()" buffered="True"> + somedef's results + + +The above definition will generate code similar to this: + +.. sourcecode:: python + + def somedef(): + context.push_buffer() + try: + context.write("somedef's results") + finally: + buf = context.pop_buffer() + return buf.getvalue() + +So that the content of ``somedef()`` is sent to a second buffer, +which is then popped off the stack and its value returned. The +speed hit inherent in buffering the output of a def is also +apparent. + +Note that the ``filter`` argument on ``%def`` also causes the def to +be buffered. This is so that the final content of the ``%def`` can +be delivered to the escaping function in one batch, which +reduces method calls and also produces more deterministic +behavior for the filtering function itself, which can possibly +be useful for a filtering function that wishes to apply a +transformation to the text as a whole. + +The other way to buffer the output of a def or any Mako callable +is by using the built-in ``capture`` function. This function +performs an operation similar to the above buffering operation +except it is specified by the caller. + +.. sourcecode:: mako + + ${" results " + capture(somedef) + " more results "} + +Note that the first argument to the ``capture`` function is +**the function itself**, not the result of calling it. This is +because the ``capture`` function takes over the job of actually +calling the target function, after setting up a buffered +environment. To send arguments to the function, just send them +to ``capture`` instead: + +.. sourcecode:: mako + + ${capture(somedef, 17, 'hi', use_paging=True)} + +The above call is equivalent to the unbuffered call: + +.. sourcecode:: mako + + ${somedef(17, 'hi', use_paging=True)} + +Decorating +========== + +.. versionadded:: 0.2.5 + +Somewhat like a filter for a ``%def`` but more flexible, the ``decorator`` +argument to ``%def`` allows the creation of a function that will +work in a similar manner to a Python decorator. The function can +control whether or not the function executes. The original +intent of this function is to allow the creation of custom cache +logic, but there may be other uses as well. + +``decorator`` is intended to be used with a regular Python +function, such as one defined in a library module. Here we'll +illustrate the python function defined in the template for +simplicities' sake: + +.. sourcecode:: mako + + <%! + def bar(fn): + def decorate(context, *args, **kw): + context.write("BAR") + fn(*args, **kw) + context.write("BAR") + return '' + return decorate + %> + + <%def name="foo()" decorator="bar"> + this is foo + + + ${foo()} + +The above template will return, with more whitespace than this, +``"BAR this is foo BAR"``. The function is the render callable +itself (or possibly a wrapper around it), and by default will +write to the context. To capture its output, use the :func:`.capture` +callable in the ``mako.runtime`` module (available in templates +as just ``runtime``): + +.. sourcecode:: mako + + <%! + def bar(fn): + def decorate(context, *args, **kw): + return "BAR" + runtime.capture(context, fn, *args, **kw) + "BAR" + return decorate + %> + + <%def name="foo()" decorator="bar"> + this is foo + + + ${foo()} + +The decorator can be used with top-level defs as well as nested +defs, and blocks too. Note that when calling a top-level def from the +:class:`.Template` API, i.e. ``template.get_def('somedef').render()``, +the decorator has to write the output to the ``context``, i.e. +as in the first example. The return value gets discarded. diff --git a/lib/mako-0.7.2/doc/build/index.rst b/lib/mako-0.7.2/doc/build/index.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/index.rst @@ -0,0 +1,22 @@ +Table of Contents +================= + +.. toctree:: + :maxdepth: 2 + + usage + syntax + defs + runtime + namespaces + inheritance + filtering + unicode + caching + +Indices and Tables +------------------ + +* :ref:`genindex` +* :ref:`search` + diff --git a/lib/mako-0.7.2/doc/build/inheritance.rst b/lib/mako-0.7.2/doc/build/inheritance.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/inheritance.rst @@ -0,0 +1,534 @@ +.. _inheritance_toplevel: + +=========== +Inheritance +=========== + +.. note:: Most of the inheritance examples here take advantage of a feature that's + new in Mako as of version 0.4.1 called the "block". This tag is very similar to + the "def" tag but is more streamlined for usage with inheritance. Note that + all of the examples here which use blocks can also use defs instead. Contrasting + usages will be illustrated. + +Using template inheritance, two or more templates can organize +themselves into an **inheritance chain**, where content and +functions from all involved templates can be intermixed. The +general paradigm of template inheritance is this: if a template +``A`` inherits from template ``B``, then template ``A`` agrees +to send the executional control to template ``B`` at runtime +(``A`` is called the **inheriting** template). Template ``B``, +the **inherited** template, then makes decisions as to what +resources from ``A`` shall be executed. + +In practice, it looks like this. Here's a hypothetical inheriting +template, ``index.html``: + +.. sourcecode:: mako + + ## index.html + <%inherit file="base.html"/> + + <%block name="header"> + this is some header content + + + this is the body content. + +And ``base.html``, the inherited template: + +.. sourcecode:: mako + + ## base.html + + +
      + <%block name="header"/> +
      + + ${self.body()} + + + + + +Here is a breakdown of the execution: + +#. When ``index.html`` is rendered, control immediately passes to + ``base.html``. +#. ``base.html`` then renders the top part of an HTML document, + then invokes the ``<%block name="header">`` block. It invokes the + underlying ``header()`` function off of a built-in namespace + called ``self`` (this namespace was first introduced in the + :doc:`Namespaces chapter ` in :ref:`namespace_self`). Since + ``index.html`` is the topmost template and also defines a block + called ``header``, it's this ``header`` block that ultimately gets + executed -- instead of the one that's present in ``base.html``. +#. Control comes back to ``base.html``. Some more HTML is + rendered. +#. ``base.html`` executes ``self.body()``. The ``body()`` + function on all template-based namespaces refers to the main + body of the template, therefore the main body of + ``index.html`` is rendered. +#. When ``<%block name="header">`` is encountered in ``index.html`` + during the ``self.body()`` call, a conditional is checked -- does the + current inherited template, i.e. ``base.html``, also define this block? If yes, + the ``<%block>`` is **not** executed here -- the inheritance + mechanism knows that the parent template is responsible for rendering + this block (and in fact it already has). In other words a block + only renders in its *basemost scope*. +#. Control comes back to ``base.html``. More HTML is rendered, + then the ``<%block name="footer">`` expression is invoked. +#. The ``footer`` block is only defined in ``base.html``, so being + the topmost definition of ``footer``, it's the one that + executes. If ``index.html`` also specified ``footer``, then + its version would **override** that of the base. +#. ``base.html`` finishes up rendering its HTML and the template + is complete, producing: + + .. sourcecode:: html + + + +
      + this is some header content +
      + + this is the body content. + + + + + +...and that is template inheritance in a nutshell. The main idea +is that the methods that you call upon ``self`` always +correspond to the topmost definition of that method. Very much +the way ``self`` works in a Python class, even though Mako is +not actually using Python class inheritance to implement this +functionality. (Mako doesn't take the "inheritance" metaphor too +seriously; while useful to setup some commonly recognized +semantics, a textual template is not very much like an +object-oriented class construct in practice). + +Nesting Blocks +============== + +The named blocks defined in an inherited template can also be nested within +other blocks. The name given to each block is globally accessible via any inheriting +template. We can add a new block ``title`` to our ``header`` block: + +.. sourcecode:: mako + + ## base.html + + +
      + <%block name="header"> +

      + <%block name="title"/> +

      + +
      + + ${self.body()} + + + + + +The inheriting template can name either or both of ``header`` and ``title``, separately +or nested themselves: + +.. sourcecode:: mako + + ## index.html + <%inherit file="base.html"/> + + <%block name="header"> + this is some header content + ${parent.header()} + + + <%block name="title"> + this is the title + + + this is the body content. + +Note when we overrode ``header``, we added an extra call ``${parent.header()}`` in order to invoke +the parent's ``header`` block in addition to our own. That's described in more detail below, +in :ref:`parent_namespace`. + +Rendering a Named Block Multiple Times +====================================== + +Recall from the section :ref:`blocks` that a named block is just like a ``<%def>``, +with some different usage rules. We can call one of our named sections distinctly, for example +a section that is used more than once, such as the title of a page: + +.. sourcecode:: mako + + + + ${self.title()} + + + <%block name="header"> +

      <%block name="title"/>

      + + ${self.body()} + + + +Where above an inheriting template can define ``<%block name="title">`` just once, and it will be +used in the base template both in the ```` section as well as the ``<h2>``. + +But what about Defs? +==================== + +The previous example used the ``<%block>`` tag to produce areas of content +to be overridden. Before Mako 0.4.1, there wasn't any such tag -- instead +there was only the ``<%def>`` tag. As it turns out, named blocks and defs are +largely interchangeable. The def simply doesn't call itself automatically, +and has more open-ended naming and scoping rules that are more flexible and similar +to Python itself, but less suited towards layout. The first example from +this chapter using defs would look like: + +.. sourcecode:: mako + + ## index.html + <%inherit file="base.html"/> + + <%def name="header()"> + this is some header content + </%def> + + this is the body content. + +And ``base.html``, the inherited template: + +.. sourcecode:: mako + + ## base.html + <html> + <body> + <div class="header"> + ${self.header()} + </div> + + ${self.body()} + + <div class="footer"> + ${self.footer()} + </div> + </body> + </html> + + <%def name="header()"/> + <%def name="footer()"> + this is the footer + </%def> + +Above, we illustrate that defs differ from blocks in that their definition +and invocation are defined in two separate places, instead of at once. You can *almost* do exactly what a +block does if you put the two together: + +.. sourcecode:: mako + + <div class="header"> + <%def name="header()"></%def>${self.header()} + </div> + +The ``<%block>`` is obviously more streamlined than the ``<%def>`` for this kind +of usage. In addition, +the above "inline" approach with ``<%def>`` does not work with nesting: + +.. sourcecode:: mako + + <head> + <%def name="header()"> + <title> + ## this won't work ! + <%def name="title()">default title</%def>${self.title()} + + ${self.header()} + + +Where above, the ``title()`` def, because it's a def within a def, is not part of the +template's exported namespace and will not be part of ``self``. If the inherited template +did define its own ``title`` def at the top level, it would be called, but the "default title" +above is not present at all on ``self`` no matter what. For this to work as expected +you'd instead need to say: + +.. sourcecode:: mako + + + <%def name="header()"> + + ${self.title()} + + ${self.header()} + + <%def name="title()"/> + + +That is, ``title`` is defined outside of any other defs so that it is in the ``self`` namespace. +It works, but the definition needs to be potentially far away from the point of render. + +A named block is always placed in the ``self`` namespace, regardless of nesting, +so this restriction is lifted: + +.. sourcecode:: mako + + ## base.html + + <%block name="header"> + + <%block name="title"/> + + + + +The above template defines ``title`` inside of ``header``, and an inheriting template can define +one or both in **any** configuration, nested inside each other or not, in order for them to be used: + +.. sourcecode:: mako + + ## index.html + <%inherit file="base.html"/> + <%block name="title"> + the title + + <%block name="header"> + the header + + +So while the ``<%block>`` tag lifts the restriction of nested blocks not being available externally, +in order to achieve this it *adds* the restriction that all block names in a single template need +to be globally unique within the template, and additionally that a ``<%block>`` can't be defined +inside of a ``<%def>``. It's a more restricted tag suited towards a more specific use case than ``<%def>``. + +Using the ``next`` Namespace to Produce Content Wrapping +======================================================== + +Sometimes you have an inheritance chain that spans more than two +templates. Or maybe you don't, but you'd like to build your +system such that extra inherited templates can be inserted in +the middle of a chain where they would be smoothly integrated. +If each template wants to define its layout just within its main +body, you can't just call ``self.body()`` to get at the +inheriting template's body, since that is only the topmost body. +To get at the body of the *next* template, you call upon the +namespace ``next``, which is the namespace of the template +**immediately following** the current template. + +Lets change the line in ``base.html`` which calls upon +``self.body()`` to instead call upon ``next.body()``: + +.. sourcecode:: mako + + ## base.html + + +
      + <%block name="header"/> +
      + + ${next.body()} + + + + + + +Lets also add an intermediate template called ``layout.html``, +which inherits from ``base.html``: + +.. sourcecode:: mako + + ## layout.html + <%inherit file="base.html"/> +
        + <%block name="toolbar"> +
      • selection 1
      • +
      • selection 2
      • +
      • selection 3
      • + +
      +
      + ${next.body()} +
      + +And finally change ``index.html`` to inherit from +``layout.html`` instead: + +.. sourcecode:: mako + + ## index.html + <%inherit file="layout.html"/> + + ## .. rest of template + +In this setup, each call to ``next.body()`` will render the body +of the next template in the inheritance chain (which can be +written as ``base.html -> layout.html -> index.html``). Control +is still first passed to the bottommost template ``base.html``, +and ``self`` still references the topmost definition of any +particular def. + +The output we get would be: + +.. sourcecode:: html + + + +
      + this is some header content +
      + +
        +
      • selection 1
      • +
      • selection 2
      • +
      • selection 3
      • +
      + +
      + this is the body content. +
      + + + + + +So above, we have the ````, ```` and +``header``/``footer`` layout of ``base.html``, we have the +``
        `` and ``mainlayout`` section of ``layout.html``, and the +main body of ``index.html`` as well as its overridden ``header`` +def. The ``layout.html`` template is inserted into the middle of +the chain without ``base.html`` having to change anything. +Without the ``next`` namespace, only the main body of +``index.html`` could be used; there would be no way to call +``layout.html``'s body content. + +.. _parent_namespace: + +Using the ``parent`` Namespace to Augment Defs +============================================== + +Lets now look at the other inheritance-specific namespace, the +opposite of ``next`` called ``parent``. ``parent`` is the +namespace of the template **immediately preceding** the current +template. What's useful about this namespace is that +defs or blocks can call upon their overridden versions. +This is not as hard as it sounds and +is very much like using the ``super`` keyword in Python. Lets +modify ``index.html`` to augment the list of selections provided +by the ``toolbar`` function in ``layout.html``: + +.. sourcecode:: mako + + ## index.html + <%inherit file="layout.html"/> + + <%block name="header"> + this is some header content + + + <%block name="toolbar"> + ## call the parent's toolbar first + ${parent.toolbar()} +
      • selection 4
      • +
      • selection 5
      • + + + this is the body content. + +Above, we implemented a ``toolbar()`` function, which is meant +to override the definition of ``toolbar`` within the inherited +template ``layout.html``. However, since we want the content +from that of ``layout.html`` as well, we call it via the +``parent`` namespace whenever we want it's content, in this case +before we add our own selections. So the output for the whole +thing is now: + +.. sourcecode:: html + + + +
        + this is some header content +
        + +
          +
        • selection 1
        • +
        • selection 2
        • +
        • selection 3
        • +
        • selection 4
        • +
        • selection 5
        • +
        + +
        + this is the body content. +
        + + + + + +and you're now a template inheritance ninja! + +Inheritable Attributes +====================== + +The :attr:`attr <.Namespace.attr>` accessor of the :class:`.Namespace` object +allows access to module level variables declared in a template. By accessing +``self.attr``, you can access regular attributes from the +inheritance chain as declared in ``<%! %>`` sections. Such as: + +.. sourcecode:: mako + + <%! + class_ = "grey" + %> + +
        + ${self.body()} +
        + +If an inheriting template overrides ``class_`` to be +``"white"``, as in: + +.. sourcecode:: mako + + <%! + class_ = "white" + %> + <%inherit file="parent.html"/> + + This is the body + +you'll get output like: + +.. sourcecode:: html + +
        + This is the body +
        + diff --git a/lib/mako-0.7.2/doc/build/namespaces.rst b/lib/mako-0.7.2/doc/build/namespaces.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/namespaces.rst @@ -0,0 +1,349 @@ +.. _namespaces_toplevel: + +========== +Namespaces +========== + +Namespaces are used to organize groups of defs into +categories, and also to "import" defs from other files. + +If the file ``components.html`` defines these two defs: + +.. sourcecode:: mako + + ## components.html + <%def name="comp1()"> + this is comp1 + + + <%def name="comp2(x)"> + this is comp2, x is ${x} + + +you can make another file, for example ``index.html``, that +pulls those two defs into a namespace called ``comp``: + +.. sourcecode:: mako + + ## index.html + <%namespace name="comp" file="components.html"/> + + Here's comp1: ${comp.comp1()} + Here's comp2: ${comp.comp2(x=5)} + +The ``comp`` variable above is an instance of +:class:`.Namespace`, a **proxy object** which delivers +method calls to the underlying template callable using the +current context. + +``<%namespace>`` also provides an ``import`` attribute which can +be used to pull the names into the local namespace, removing the +need to call it via the "``.``" operator. When ``import`` is used, the +``name`` attribute is optional. + +.. sourcecode:: mako + + <%namespace file="components.html" import="comp1, comp2"/> + + Heres comp1: ${comp1()} + Heres comp2: ${comp2(x=5)} + +``import`` also supports the "``*``" operator: + +.. sourcecode:: mako + + <%namespace file="components.html" import="*"/> + + Heres comp1: ${comp1()} + Heres comp2: ${comp2(x=5)} + +The names imported by the ``import`` attribute take precedence +over any names that exist within the current context. + +.. note:: In current versions of Mako, usage of ``import='*'`` is + known to decrease performance of the template. This will be + fixed in a future release. + +The ``file`` argument allows expressions -- if looking for +context variables, the ``context`` must be named explicitly: + +.. sourcecode:: mako + + <%namespace name="dyn" file="${context['namespace_name']}"/> + +Ways to Call Namespaces +======================= + +There are essentially four ways to call a function from a +namespace. + +The "expression" format, as described previously. Namespaces are +just Python objects with functions on them, and can be used in +expressions like any other function: + +.. sourcecode:: mako + + ${mynamespace.somefunction('some arg1', 'some arg2', arg3='some arg3', arg4='some arg4')} + +Synonymous with the "expression" format is the "custom tag" +format, when a "closed" tag is used. This format, introduced in +Mako 0.2.3, allows the usage of a "custom" Mako tag, with the +function arguments passed in using named attributes: + +.. sourcecode:: mako + + <%mynamespace:somefunction arg1="some arg1" arg2="some arg2" arg3="some arg3" arg4="some arg4"/> + +When using tags, the values of the arguments are taken as +literal strings by default. To embed Python expressions as +arguments, use the embedded expression format: + +.. sourcecode:: mako + + <%mynamespace:somefunction arg1="${someobject.format()}" arg2="${somedef(5, 12)}"/> + +The "custom tag" format is intended mainly for namespace +functions which recognize body content, which in Mako is known +as a "def with embedded content": + +.. sourcecode:: mako + + <%mynamespace:somefunction arg1="some argument" args="x, y"> + Some record: ${x}, ${y} + + +The "classic" way to call defs with embedded content is the ``<%call>`` tag: + +.. sourcecode:: mako + + <%call expr="mynamespace.somefunction(arg1='some argument')" args="x, y"> + Some record: ${x}, ${y} + + +For information on how to construct defs that embed content from +the caller, see :ref:`defs_with_content`. + +.. _namespaces_python_modules: + +Namespaces from Regular Python Modules +====================================== + +Namespaces can also import regular Python functions from +modules. These callables need to take at least one argument, +``context``, an instance of :class:`.Context`. A module file +``some/module.py`` might contain the callable: + +.. sourcecode:: python + + def my_tag(context): + context.write("hello world") + return '' + +A template can use this module via: + +.. sourcecode:: mako + + <%namespace name="hw" module="some.module"/> + + ${hw.my_tag()} + +Note that the ``context`` argument is not needed in the call; +the :class:`.Namespace` tag creates a locally-scoped callable which +takes care of it. The ``return ''`` is so that the def does not +dump a ``None`` into the output stream -- the return value of any +def is rendered after the def completes, in addition to whatever +was passed to :meth:`.Context.write` within its body. + +If your def is to be called in an "embedded content" context, +that is as described in :ref:`defs_with_content`, you should use +the :func:`.supports_caller` decorator, which will ensure that Mako +will ensure the correct "caller" variable is available when your +def is called, supporting embedded content: + +.. sourcecode:: python + + from mako.runtime import supports_caller + + @supports_caller + def my_tag(context): + context.write("
        ") + context['caller'].body() + context.write("
        ") + return '' + +Capturing of output is available as well, using the +outside-of-templates version of the :func:`.capture` function, +which accepts the "context" as its first argument: + +.. sourcecode:: python + + from mako.runtime import supports_caller, capture + + @supports_caller + def my_tag(context): + return "
        %s
        " % \ + capture(context, context['caller'].body, x="foo", y="bar") + +Declaring Defs in Namespaces +============================ + +The ``<%namespace>`` tag supports the definition of ``<%def>``\ s +directly inside the tag. These defs become part of the namespace +like any other function, and will override the definitions +pulled in from a remote template or module: + +.. sourcecode:: mako + + ## define a namespace + <%namespace name="stuff"> + <%def name="comp1()"> + comp1 + + + + ## then call it + ${stuff.comp1()} + +.. _namespaces_body: + +The ``body()`` Method +===================== + +Every namespace that is generated from a template contains a +method called ``body()``. This method corresponds to the main +body of the template, and plays its most important roles when +using inheritance relationships as well as +def-calls-with-content. + +Since the ``body()`` method is available from a namespace just +like all the other defs defined in a template, what happens if +you send arguments to it? By default, the ``body()`` method +accepts no positional arguments, and for usefulness in +inheritance scenarios will by default dump all keyword arguments +into a dictionary called ``pageargs``. But if you actually want +to get at the keyword arguments, Mako recommends you define your +own argument signature explicitly. You do this via using the +``<%page>`` tag: + +.. sourcecode:: mako + + <%page args="x, y, someval=8, scope='foo', **kwargs"/> + +A template which defines the above signature requires that the +variables ``x`` and ``y`` are defined, defines default values +for ``someval`` and ``scope``, and sets up ``**kwargs`` to +receive all other keyword arguments. If ``**kwargs`` or similar +is not present, the argument ``**pageargs`` gets tacked on by +Mako. When the template is called as a top-level template (i.e. +via :meth:`~.Template.render`) or via the ``<%include>`` tag, the +values for these arguments will be pulled from the ``Context``. +In all other cases, i.e. via calling the ``body()`` method, the +arguments are taken as ordinary arguments from the method call. +So above, the body might be called as: + +.. sourcecode:: mako + + ${self.body(5, y=10, someval=15, delta=7)} + +The :class:`.Context` object also supplies a :attr:`~.Context.kwargs` accessor, for +cases when you'd like to pass along whatever is in the context to +a ``body()`` callable: + +.. sourcecode:: mako + + ${next.body(**context.kwargs)} + +The usefulness of calls like the above become more apparent when +one works with inheriting templates. For more information on +this, as well as the meanings of the names ``self`` and +``next``, see :ref:`inheritance_toplevel`. + +.. _namespaces_builtin: + +Built-in Namespaces +=================== + +The namespace is so great that Mako gives your template one (or +two) for free. The names of these namespaces are ``local`` and +``self``. Other built-in namespaces include ``parent`` and +``next``, which are optional and are described in +:ref:`inheritance_toplevel`. + +.. _namespace_local: + +``local`` +--------- + +The ``local`` namespace is basically the namespace for the +currently executing template. This means that all of the top +level defs defined in your template, as well as your template's +``body()`` function, are also available off of the ``local`` +namespace. + +The ``local`` namespace is also where properties like ``uri``, +``filename``, and ``module`` and the ``get_namespace`` method +can be particularly useful. + +.. _namespace_self: + +``self`` +-------- + +The ``self`` namespace, in the case of a template that does not +use inheritance, is synonymous with ``local``. If inheritance is +used, then ``self`` references the topmost template in the +inheritance chain, where it is most useful for providing the +ultimate form of various "method" calls which may have been +overridden at various points in an inheritance chain. See +:ref:`inheritance_toplevel`. + +Inheritable Namespaces +====================== + +The ``<%namespace>`` tag includes an optional attribute +``inheritable="True"``, which will cause the namespace to be +attached to the ``self`` namespace. Since ``self`` is globally +available throughout an inheritance chain (described in the next +section), all the templates in an inheritance chain can get at +the namespace imported in a super-template via ``self``. + +.. sourcecode:: mako + + ## base.html + <%namespace name="foo" file="foo.html" inheritable="True"/> + + ${next.body()} + + ## somefile.html + <%inherit file="base.html"/> + + ${self.foo.bar()} + +This allows a super-template to load a whole bunch of namespaces +that its inheriting templates can get to, without them having to +explicitly load those namespaces themselves. + +The ``import="*"`` part of the ``<%namespace>`` tag doesn't yet +interact with the ``inheritable`` flag, so currently you have to +use the explicit namespace name off of ``self``, followed by the +desired function name. But more on this in a future release. + +API Reference +============= + +.. autoclass:: mako.runtime.Namespace + :show-inheritance: + :members: + +.. autoclass:: mako.runtime.TemplateNamespace + :show-inheritance: + :members: + +.. autoclass:: mako.runtime.ModuleNamespace + :show-inheritance: + :members: + +.. autofunction:: mako.runtime.supports_caller + +.. autofunction:: mako.runtime.capture + diff --git a/lib/mako-0.7.2/doc/build/runtime.rst b/lib/mako-0.7.2/doc/build/runtime.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/runtime.rst @@ -0,0 +1,448 @@ +.. _runtime_toplevel: + +============================ +The Mako Runtime Environment +============================ + +This section describes a little bit about the objects and +built-in functions that are available in templates. + +.. _context: + +Context +======= + +The :class:`.Context` is the central object that is created when +a template is first executed, and is responsible for handling +all communication with the outside world. Within the template +environment, it is available via the :ref:`reserved name ` +``context``. The :class:`.Context` includes two +major components, one of which is the output buffer, which is a +file-like object such as Python's ``StringIO`` or similar, and +the other a dictionary of variables that can be freely +referenced within a template; this dictionary is a combination +of the arguments sent to the :meth:`~.Template.render` function and +some built-in variables provided by Mako's runtime environment. + +The Buffer +---------- + +The buffer is stored within the :class:`.Context`, and writing +to it is achieved by calling the :meth:`~.Context.write` method +-- in a template this looks like ``context.write('some string')``. +You usually don't need to care about this, as all text within a template, as +well as all expressions provided by ``${}``, automatically send +everything to this method. The cases you might want to be aware +of its existence are if you are dealing with various +filtering/buffering scenarios, which are described in +:ref:`filtering_toplevel`, or if you want to programmatically +send content to the output stream, such as within a ``<% %>`` +block. + +.. sourcecode:: mako + + <% + context.write("some programmatic text") + %> + +The actual buffer may or may not be the original buffer sent to +the :class:`.Context` object, as various filtering/caching +scenarios may "push" a new buffer onto the context's underlying +buffer stack. For this reason, just stick with +``context.write()`` and content will always go to the topmost +buffer. + +.. _context_vars: + +Context Variables +----------------- + +When your template is compiled into a Python module, the body +content is enclosed within a Python function called +``render_body``. Other top-level defs defined in the template are +defined within their own function bodies which are named after +the def's name with the prefix ``render_`` (i.e. ``render_mydef``). +One of the first things that happens within these functions is +that all variable names that are referenced within the function +which are not defined in some other way (i.e. such as via +assignment, module level imports, etc.) are pulled from the +:class:`.Context` object's dictionary of variables. This is how you're +able to freely reference variable names in a template which +automatically correspond to what was passed into the current +:class:`.Context`. + +* **What happens if I reference a variable name that is not in + the current context?** - The value you get back is a special + value called ``UNDEFINED``, or if the ``strict_undefined=True`` flag + is used a ``NameError`` is raised. ``UNDEFINED`` is just a simple global + variable with the class :class:`mako.runtime.Undefined`. The + ``UNDEFINED`` object throws an error when you call ``str()`` on + it, which is what happens if you try to use it in an + expression. +* **UNDEFINED makes it hard for me to find what name is missing** - An alternative + is to specify the option ``strict_undefined=True`` + to the :class:`.Template` or :class:`.TemplateLookup`. This will cause + any non-present variables to raise an immediate ``NameError`` + which includes the name of the variable in its message + when :meth:`~.Template.render` is called -- ``UNDEFINED`` is not used. + + .. versionadded:: 0.3.6 + +* **Why not just return None?** Using ``UNDEFINED``, or + raising a ``NameError`` is more + explicit and allows differentiation between a value of ``None`` + that was explicitly passed to the :class:`.Context` and a value that + wasn't present at all. +* **Why raise an exception when you call str() on it ? Why not + just return a blank string?** - Mako tries to stick to the + Python philosophy of "explicit is better than implicit". In + this case, it's decided that the template author should be made + to specifically handle a missing value rather than + experiencing what may be a silent failure. Since ``UNDEFINED`` + is a singleton object just like Python's ``True`` or ``False``, + you can use the ``is`` operator to check for it: + + .. sourcecode:: mako + + % if someval is UNDEFINED: + someval is: no value + % else: + someval is: ${someval} + % endif + +Another facet of the :class:`.Context` is that its dictionary of +variables is **immutable**. Whatever is set when +:meth:`~.Template.render` is called is what stays. Of course, since +its Python, you can hack around this and change values in the +context's internal dictionary, but this will probably will not +work as well as you'd think. The reason for this is that Mako in +many cases creates copies of the :class:`.Context` object, which +get sent to various elements of the template and inheriting +templates used in an execution. So changing the value in your +local :class:`.Context` will not necessarily make that value +available in other parts of the template's execution. Examples +of where Mako creates copies of the :class:`.Context` include +within top-level def calls from the main body of the template +(the context is used to propagate locally assigned variables +into the scope of defs; since in the template's body they appear +as inlined functions, Mako tries to make them act that way), and +within an inheritance chain (each template in an inheritance +chain has a different notion of ``parent`` and ``next``, which +are all stored in unique :class:`.Context` instances). + +* **So what if I want to set values that are global to everyone + within a template request?** - All you have to do is provide a + dictionary to your :class:`.Context` when the template first + runs, and everyone can just get/set variables from that. Lets + say its called ``attributes``. + + Running the template looks like: + + .. sourcecode:: python + + output = template.render(attributes={}) + + Within a template, just reference the dictionary: + + .. sourcecode:: mako + + <% + attributes['foo'] = 'bar' + %> + 'foo' attribute is: ${attributes['foo']} + +* **Why can't "attributes" be a built-in feature of the + Context?** - This is an area where Mako is trying to make as + few decisions about your application as it possibly can. + Perhaps you don't want your templates to use this technique of + assigning and sharing data, or perhaps you have a different + notion of the names and kinds of data structures that should + be passed around. Once again Mako would rather ask the user to + be explicit. + +Context Methods and Accessors +----------------------------- + +Significant members of :class:`.Context` include: + +* ``context[key]`` / ``context.get(key, default=None)`` - + dictionary-like accessors for the context. Normally, any + variable you use in your template is automatically pulled from + the context if it isn't defined somewhere already. Use the + dictionary accessor and/or ``get`` method when you want a + variable that *is* already defined somewhere else, such as in + the local arguments sent to a ``%def`` call. If a key is not + present, like a dictionary it raises ``KeyError``. +* ``keys()`` - all the names defined within this context. +* ``kwargs`` - this returns a **copy** of the context's + dictionary of variables. This is useful when you want to + propagate the variables in the current context to a function + as keyword arguments, i.e.: + + .. sourcecode:: mako + + ${next.body(**context.kwargs)} + +* ``write(text)`` - write some text to the current output + stream. +* ``lookup`` - returns the :class:`.TemplateLookup` instance that is + used for all file-lookups within the current execution (even + though individual :class:`.Template` instances can conceivably have + different instances of a :class:`.TemplateLookup`, only the + :class:`.TemplateLookup` of the originally-called :class:`.Template` gets + used in a particular execution). + +.. _loop_context: + +The Loop Context +================ + +Within ``% for`` blocks, the :ref:`reserved name` ``loop`` +is available. ``loop`` tracks the progress of +the ``for`` loop and makes it easy to use the iteration state to control +template behavior: + +.. sourcecode:: mako + +
          + % for a in ("one", "two", "three"): +
        • Item ${loop.index}: ${a}
        • + % endfor +
        + +.. versionadded:: 0.7 + +Iterations +---------- + +Regardless of the type of iterable you're looping over, ``loop`` always tracks +the 0-indexed iteration count (available at ``loop.index``), its parity +(through the ``loop.even`` and ``loop.odd`` bools), and ``loop.first``, a bool +indicating whether the loop is on its first iteration. If your iterable +provides a ``__len__`` method, ``loop`` also provides access to +a count of iterations remaining at ``loop.reverse_index`` and ``loop.last``, +a bool indicating whether the loop is on its last iteration; accessing these +without ``__len__`` will raise a ``TypeError``. + +Cycling +------- + +Cycling is available regardless of whether the iterable you're using provides +a ``__len__`` method. Prior to Mako 0.7, you might have generated a simple +zebra striped list using ``enumerate``: + +.. sourcecode:: mako + +
          + % for i, item in enumerate(('spam', 'ham', 'eggs')): +
        • ${item}
        • + % endfor +
        + +With ``loop.cycle``, you get the same results with cleaner code and less prep work: + +.. sourcecode:: mako + +
          + % for item in ('spam', 'ham', 'eggs'): +
        • ${item}
        • + % endfor +
        + +Both approaches produce output like the following: + +.. sourcecode:: html + +
          +
        • spam
        • +
        • ham
        • +
        • eggs
        • +
        + +Parent Loops +------------ + +Loop contexts can also be transparently nested, and the Mako runtime will do +the right thing and manage the scope for you. You can access the parent loop +context through ``loop.parent``. + +This allows you to reach all the way back up through the loop stack by +chaining ``parent`` attribute accesses, i.e. ``loop.parent.parent....`` as +long as the stack depth isn't exceeded. For example, you can use the parent +loop to make a checkered table: + +.. sourcecode:: mako + +
      + % for consonant in 'pbj': + + % for vowel in 'iou': + + % endfor + + % endfor +
      + ${consonant + vowel}t +
      + +.. sourcecode:: html + + + + + + + + + + + + + + + + + +
      + pit + + pot + + put +
      + bit + + bot + + but +
      + jit + + jot + + jut +
      + +.. _migrating_loop: + +Migrating Legacy Templates that Use the Word "loop" +--------------------------------------------------- + +.. versionchanged:: 0.7 + The ``loop`` name is now :ref:`reserved ` in Mako, + which means a template that refers to a variable named ``loop`` + won't function correctly when used in Mako 0.7. + +To ease the transition for such systems, the feature can be disabled across the board for +all templates, then re-enabled on a per-template basis for those templates which wish +to make use of the new system. + +First, the ``enable_loop=False`` flag is passed to either the :class:`.TemplateLookup` +or :class:`.Template` object in use: + +.. sourcecode:: python + + lookup = TemplateLookup(directories=['/docs'], enable_loop=False) + +or: + +.. sourcecode:: python + + template = Template("some template", enable_loop=False) + +An individual template can make usage of the feature when ``enable_loop`` is set to +``False`` by switching it back on within the ``<%page>`` tag: + +.. sourcecode:: mako + + <%page enable_loop="True"/> + + % for i in collection: + ${i} ${loop.index} + % endfor + +Using the above scheme, it's safe to pass the name ``loop`` to the :meth:`.Template.render` +method as well as to freely make usage of a variable named ``loop`` within a template, provided +the ``<%page>`` tag doesn't override it. New templates that want to use the ``loop`` context +can then set up ``<%page enable_loop="True"/>`` to use the new feature without affecting +old templates. + +All the Built-in Names +====================== + +A one-stop shop for all the names Mako defines. Most of these +names are instances of :class:`.Namespace`, which are described +in the next section, :ref:`namespaces_toplevel`. Also, most of +these names other than ``context``, ``UNDEFINED``, and ``loop`` are +also present *within* the :class:`.Context` itself. The names +``context``, ``loop`` and ``UNDEFINED`` themselves can't be passed +to the context and can't be substituted -- see the section :ref:`reserved_names`. + +* ``context`` - this is the :class:`.Context` object, introduced + at :ref:`context`. +* ``local`` - the namespace of the current template, described + in :ref:`namespaces_builtin`. +* ``self`` - the namespace of the topmost template in an + inheritance chain (if any, otherwise the same as ``local``), + mostly described in :ref:`inheritance_toplevel`. +* ``parent`` - the namespace of the parent template in an + inheritance chain (otherwise undefined); see + :ref:`inheritance_toplevel`. +* ``next`` - the namespace of the next template in an + inheritance chain (otherwise undefined); see + :ref:`inheritance_toplevel`. +* ``caller`` - a "mini" namespace created when using the + ``<%call>`` tag to define a "def call with content"; described + in :ref:`defs_with_content`. +* ``loop`` - this provides access to :class:`.LoopContext` objects when + they are requested within ``% for`` loops, introduced at :ref:`loop_context`. +* ``capture`` - a function that calls a given def and captures + its resulting content into a string, which is returned. Usage + is described in :ref:`filtering_toplevel`. +* ``UNDEFINED`` - a global singleton that is applied to all + otherwise uninitialized template variables that were not + located within the :class:`.Context` when rendering began, + unless the :class:`.Template` flag ``strict_undefined`` + is set to ``True``. ``UNDEFINED`` is + an instance of :class:`.Undefined`, and raises an + exception when its ``__str__()`` method is called. +* ``pageargs`` - this is a dictionary which is present in a + template which does not define any ``**kwargs`` section in its + ``<%page>`` tag. All keyword arguments sent to the ``body()`` + function of a template (when used via namespaces) go here by + default unless otherwise defined as a page argument. If this + makes no sense, it shouldn't; read the section + :ref:`namespaces_body`. + +.. _reserved_names: + +Reserved Names +-------------- + +Mako has a few names that are considered to be "reserved" and can't be used +as variable names. + +.. versionchanged:: 0.7 + Mako raises an error if these words are found passed to the template + as context arguments, whereas in previous versions they'd be silently + ignored or lead to other error messages. + +* ``context`` - see :ref:`context`. +* ``UNDEFINED`` - see :ref:`context_vars`. +* ``loop`` - see :ref:`loop_context`. Note this can be disabled for legacy templates + via the ``enable_loop=False`` argument; see :ref:`migrating_loop`. + +API Reference +============= + +.. autoclass:: mako.runtime.Context + :show-inheritance: + :members: + +.. autoclass:: mako.runtime.LoopContext + :show-inheritance: + :members: + +.. autoclass:: mako.runtime.Undefined + :show-inheritance: + diff --git a/lib/mako-0.7.2/doc/build/static/docs.css b/lib/mako-0.7.2/doc/build/static/docs.css new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/static/docs.css @@ -0,0 +1,438 @@ +/* global */ + +body { + background-color: #FDFBFC; + margin:38px; + color:#333333; +} + +a { + font-weight:normal; + text-decoration:none; +} + +form { + display:inline; +} + +/* hyperlinks */ + +a:link, a:visited, a:active { + color:#0000FF; +} +a:hover { + color:#700000; + text-decoration:underline; +} + +/* paragraph links after sections. + These aren't visible until hovering + over the tag, then have a + "reverse video" effect over the actual + link + */ + +a.headerlink { + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +a.headerlink:hover { + background-color: #990000; + color: white; +} + + +/* Container setup */ + +#docs-container { + max-width:1000px; +} + + +/* header/footer elements */ + +#docs-header h1 { + font-size:20px; + color: #222222; + margin: 0; + padding: 0; +} + +#docs-header { + font-family:Tahoma, Geneva,sans-serif; + + font-size:.9em; + +} + +#docs-top-navigation, +#docs-bottom-navigation { + font-family: Tahoma, Geneva, sans-serif; + background-color: #EEE; + border: solid 1px #CCC; + padding:10px; + font-size:.9em; +} + +#docs-top-navigation { + margin:10px 0px 10px 0px; + line-height:1.2em; +} + +.docs-navigation-links { + font-family:Tahoma, Geneva,sans-serif; +} + +#docs-bottom-navigation { + float:right; + margin: 1em 0 1em 5px; +} + +#docs-copyright { + font-size:.85em; + padding:5px 0px; +} + +#docs-header h1, +#docs-top-navigation h1, +#docs-top-navigation h2 { + font-family:Tahoma,Geneva,sans-serif; + font-weight:normal; +} + +#docs-top-navigation h2 { + margin:16px 4px 7px 5px; + font-size:2em; +} + +#docs-search { + float:right; +} + +#docs-top-page-control { + float:right; + width:350px; +} + +#docs-top-page-control ul { + padding:0; + margin:0; +} + +#docs-top-page-control li { + list-style-type:none; + padding:1px 8px; +} + + +#docs-container .version-num { + font-weight: bold; +} + + +/* content container, sidebar */ + +#docs-body-container { + background-color:#EFEFEF; + border: solid 1px #CCC; + +} + +#docs-body, +#docs-sidebar + { + /*font-family: helvetica, arial, sans-serif; + font-size:.9em;*/ + + font-family: Tahoma, Geneva, sans-serif; + /*font-size:.85em;*/ + line-height:1.5em; + +} + +#docs-sidebar > ul { + font-size:.9em; +} + +#docs-sidebar { + float:left; + width:212px; + padding: 10px 0 0 15px; + /*font-size:.85em;*/ +} + +#docs-sidebar h3, #docs-sidebar h4 { + background-color: #DDDDDD; + color: #222222; + font-family: Tahoma, Geneva,sans-serif; + font-size: 1.1em; + font-weight: normal; + margin: 10px 0 0 -15px; + padding: 5px 10px 5px 10px; + text-shadow: 1px 1px 0 white; + width:210px; +} + +#docs-sidebar h3 a, #docs-sidebar h4 a { + color: #222222; +} +#docs-sidebar ul { + margin: 10px 10px 10px 0px; + padding: 0; + list-style: none outside none; +} + + +#docs-sidebar ul ul { + margin-bottom: 0; + margin-top: 0; + list-style: square outside none; + margin-left: 20px; +} + +#docs-body { + background-color:#FFFFFF; + padding:1px 10px 10px 10px; +} + +#docs-body.withsidebar { + margin: 0 0 0 230px; + border-left:3px solid #DFDFDF; +} + +#docs-body h1, +#docs-body h2, +#docs-body h3, +#docs-body h4 { + font-family:Tahoma, Geneva, sans-serif; +} + +#docs-body h1 { + /* hide the

      for each content section. */ + display:none; + font-size:1.8em; +} + +#docs-body h2 { + font-size:1.6em; +} + +#docs-body h3 { + font-size:1.4em; +} + +/* SQL popup, code styles */ + +.highlight { + background:none; +} + +#docs-container pre { + font-size:1.2em; +} + +#docs-container .pre { + font-size:1.1em; +} + +#docs-container pre { + background-color: #f0f0f0; + border: solid 1px #ccc; + box-shadow: 2px 2px 3px #DFDFDF; + padding:10px; + margin: 5px 0px 5px 0px; + overflow:auto; + line-height:1.3em; +} + +.popup_sql, .show_sql +{ + background-color: #FBFBEE; + padding:5px 10px; + margin:10px -5px; + border:1px dashed; +} + +/* the [SQL] links used to display SQL */ +#docs-container .sql_link +{ + font-weight:normal; + font-family: arial, sans-serif; + font-size:.9em; + text-transform: uppercase; + color:#990000; + border:1px solid; + padding:1px 2px 1px 2px; + margin:0px 10px 0px 15px; + float:right; + line-height:1.2em; +} + +#docs-container a.sql_link, +#docs-container .sql_link +{ + text-decoration: none; + padding:1px 2px; +} + +#docs-container a.sql_link:hover { + text-decoration: none; + color:#fff; + border:1px solid #900; + background-color: #900; +} + +/* docutils-specific elements */ + +th.field-name { + text-align:right; +} + +div.note, div.warning, p.deprecated, div.topic { + background-color:#EEFFEF; +} + + +div.admonition, div.topic, p.deprecated, p.versionadded, p.versionchanged { + border:1px solid #CCCCCC; + padding:5px 10px; + font-size:.9em; + box-shadow: 2px 2px 3px #DFDFDF; +} + +div.warning .admonition-title { + color:#FF0000; +} + +div.admonition .admonition-title, div.topic .topic-title { + font-weight:bold; +} + +.viewcode-back, .viewcode-link { + float:right; +} + +dl.function > dt, +dl.attribute > dt, +dl.classmethod > dt, +dl.method > dt, +dl.class > dt, +dl.exception > dt +{ + background-color:#F0F0F0; + margin:25px -10px 10px 10px; + padding: 0px 10px; +} + +p.versionadded span.versionmodified, +p.versionchanged span.versionmodified, +p.deprecated span.versionmodified { + background-color: #F0F0F0; + font-style: italic; +} + +dt:target, span.highlight { + background-color:#FBE54E; +} + +a.headerlink { + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink { + visibility: visible; +} + +a.headerlink:hover { + background-color: #00f; + color: white; +} + +.clearboth { + clear:both; +} + +tt.descname { + background-color:transparent; + font-size:1.2em; + font-weight:bold; +} + +tt.descclassname { + background-color:transparent; +} + +tt { + background-color:#ECF0F3; + padding:0 1px; +} + +/* syntax highlighting overrides */ +.k, .kn {color:#0908CE;} +.o {color:#BF0005;} +.go {color:#804049;} + + +/* special "index page" sections + with specific formatting +*/ + +div#sqlalchemy-documentation { + font-size:.95em; +} +div#sqlalchemy-documentation em { + font-style:normal; +} +div#sqlalchemy-documentation .rubric{ + font-size:14px; + background-color:#EEFFEF; + padding:5px; + border:1px solid #BFBFBF; +} +div#sqlalchemy-documentation a, div#sqlalchemy-documentation li { + padding:5px 0px; +} + +div#getting-started { + border-bottom:1px solid; +} + +div#sqlalchemy-documentation div#sqlalchemy-orm { + float:left; + width:48%; +} + +div#sqlalchemy-documentation div#sqlalchemy-core { + float:left; + width:48%; + margin:0; + padding-left:10px; + border-left:1px solid; +} + +div#dialect-documentation { + border-top:1px solid; + /*clear:left;*/ +} diff --git a/lib/mako-0.7.2/doc/build/static/makoLogo.png b/lib/mako-0.7.2/doc/build/static/makoLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c43c087eb48ebfc2223b76cf3df2fa7868c2a72b GIT binary patch [stripped] diff --git a/lib/mako-0.7.2/doc/build/static/site.css b/lib/mako-0.7.2/doc/build/static/site.css new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/static/site.css @@ -0,0 +1,82 @@ +body { + font-family: Tahoma, Geneva, sans-serif; + line-height:1.4em; + margin:15px; + background-color:#FFFFFF; +} +img {border:none;} +a { text-decoration: none;} +a:visited { color: #2929ff;} +a:hover { color: #0000ff;} + +#wrap { + margin:0 auto; + max-width:1024px; + min-width:480px; + position:relative; + +} +h1 { + font-size:1.6em; + font-weight:bold; +} + +h2 { + font-size:1.1em; + font-weight:bold; + margin:10px 0px 10px 0px; +} + +.clearfix{ + clear:both; +} + +.red { + font-weight:bold; + color:#FF0000; +} +.rightbar { + float:right; + margin:10px 30px 10px 30px; +} +.slogan { + margin-top:10px; +} +.toolbar { + margin-top:20px; +} +.copyright { + font-size:.8em; + text-align:center; + color:909090; +} +.pylogo { + text-align:right; + float:right; +} +.code { + font-family:monospace; +} + +li { + margin:1px 0px 1px 0px; +} + +.speedchart td { + font-size:small; +} + +pre.codesample { + margin: 1.5em; + padding: .5em; + font-size: .95em; + line-height:1em; + background-color: #eee; + border: 1px solid #ccc; + width:450px; + overflow:auto; +} + +#speedchart { + margin:5px 10px 5px 10px; +} diff --git a/lib/mako-0.7.2/doc/build/syntax.rst b/lib/mako-0.7.2/doc/build/syntax.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/syntax.rst @@ -0,0 +1,469 @@ +.. _syntax_toplevel: + +====== +Syntax +====== + +A Mako template is parsed from a text stream containing any kind +of content, XML, HTML, email text, etc. The template can further +contain Mako-specific directives which represent variable and/or +expression substitutions, control structures (i.e. conditionals +and loops), server-side comments, full blocks of Python code, as +well as various tags that offer additional functionality. All of +these constructs compile into real Python code. This means that +you can leverage the full power of Python in almost every aspect +of a Mako template. + +Expression Substitution +======================= + +The simplest expression is just a variable substitution. The +syntax for this is the ``${}`` construct, which is inspired by +Perl, Genshi, JSP EL, and others: + +.. sourcecode:: mako + + this is x: ${x} + +Above, the string representation of ``x`` is applied to the +template's output stream. If you're wondering where ``x`` comes +from, it's usually from the :class:`.Context` supplied to the +template's rendering function. If ``x`` was not supplied to the +template and was not otherwise assigned locally, it evaluates to +a special value ``UNDEFINED``. More on that later. + +The contents within the ``${}`` tag are evaluated by Python +directly, so full expressions are OK: + +.. sourcecode:: mako + + pythagorean theorem: ${pow(x,2) + pow(y,2)} + +The results of the expression are evaluated into a string result +in all cases before being rendered to the output stream, such as +the above example where the expression produces a numeric +result. + +Expression Escaping +=================== + +Mako includes a number of built-in escaping mechanisms, +including HTML, URI and XML escaping, as well as a "trim" +function. These escapes can be added to an expression +substitution using the ``|`` operator: + +.. sourcecode:: mako + + ${"this is some text" | u} + +The above expression applies URL escaping to the expression, and +produces ``this+is+some+text``. The ``u`` name indicates URL +escaping, whereas ``h`` represents HTML escaping, ``x`` +represents XML escaping, and ``trim`` applies a trim function. + +Read more about built-in filtering functions, including how to +make your own filter functions, in :ref:`filtering_toplevel`. + +Control Structures +================== + +A control structure refers to all those things that control the +flow of a program -- conditionals (i.e. ``if``/``else``), loops (like +``while`` and ``for``), as well as things like ``try``/``except``. In Mako, +control structures are written using the ``%`` marker followed +by a regular Python control expression, and are "closed" by +using another ``%`` marker with the tag "``end``", where +"````" is the keyword of the expression: + +.. sourcecode:: mako + + % if x==5: + this is some output + % endif + +The ``%`` can appear anywhere on the line as long as no text +precedes it; indentation is not significant. The full range of +Python "colon" expressions are allowed here, including +``if``/``elif``/``else``, ``while``, ``for``, and even ``def``, although +Mako has a built-in tag for defs which is more full-featured. + +.. sourcecode:: mako + + % for a in ['one', 'two', 'three', 'four', 'five']: + % if a[0] == 't': + its two or three + % elif a[0] == 'f': + four/five + % else: + one + % endif + % endfor + +The ``%`` sign can also be "escaped", if you actually want to +emit a percent sign as the first non whitespace character on a +line, by escaping it as in ``%%``: + +.. sourcecode:: mako + + %% some text + + %% some more text + +The Loop Context +---------------- + +The **loop context** provides additional information about a loop +while inside of a ``% for`` structure: + +.. sourcecode:: mako + +
        + % for a in ("one", "two", "three"): +
      • Item ${loop.index}: ${a}
      • + % endfor +
      + +See :ref:`loop_context` for more information on this feature. + +.. versionadded:: 0.7 + +Comments +======== + +Comments come in two varieties. The single line comment uses +``##`` as the first non-space characters on a line: + +.. sourcecode:: mako + + ## this is a comment. + ...text ... + +A multiline version exists using ``<%doc> ...text... ``: + +.. sourcecode:: mako + + <%doc> + these are comments + more comments + + +Newline Filters +=============== + +The backslash ("``\``") character, placed at the end of any +line, will consume the newline character before continuing to +the next line: + +.. sourcecode:: mako + + here is a line that goes onto \ + another line. + +The above text evaluates to: + +.. sourcecode:: text + + here is a line that goes onto another line. + +Python Blocks +============= + +Any arbitrary block of python can be dropped in using the ``<% +%>`` tags: + +.. sourcecode:: mako + + this is a template + <% + x = db.get_resource('foo') + y = [z.element for z in x if x.frobnizzle==5] + %> + % for elem in y: + element: ${elem} + % endfor + +Within ``<% %>``, you're writing a regular block of Python code. +While the code can appear with an arbitrary level of preceding +whitespace, it has to be consistently formatted with itself. +Mako's compiler will adjust the block of Python to be consistent +with the surrounding generated Python code. + +Module-level Blocks +=================== + +A variant on ``<% %>`` is the module-level code block, denoted +by ``<%! %>``. Code within these tags is executed at the module +level of the template, and not within the rendering function of +the template. Therefore, this code does not have access to the +template's context and is only executed when the template is +loaded into memory (which can be only once per application, or +more, depending on the runtime environment). Use the ``<%! %>`` +tags to declare your template's imports, as well as any +pure-Python functions you might want to declare: + +.. sourcecode:: mako + + <%! + import mylib + import re + + def filter(text): + return re.sub(r'^@', '', text) + %> + +Any number of ``<%! %>`` blocks can be declared anywhere in a +template; they will be rendered in the resulting module +in a single contiguous block above all render callables, +in the order in which they appear in the source template. + +Tags +==== + +The rest of what Mako offers takes place in the form of tags. +All tags use the same syntax, which is similar to an XML tag +except that the first character of the tag name is a ``%`` +character. The tag is closed either by a contained slash +character, or an explicit closing tag: + +.. sourcecode:: mako + + <%include file="foo.txt"/> + + <%def name="foo" buffered="True"> + this is a def + + +All tags have a set of attributes which are defined for each +tag. Some of these attributes are required. Also, many +attributes support **evaluation**, meaning you can embed an +expression (using ``${}``) inside the attribute text: + +.. sourcecode:: mako + + <%include file="/foo/bar/${myfile}.txt"/> + +Whether or not an attribute accepts runtime evaluation depends +on the type of tag and how that tag is compiled into the +template. The best way to find out if you can stick an +expression in is to try it! The lexer will tell you if it's not +valid. + +Heres a quick summary of all the tags: + +``<%page>`` +----------- + +This tag defines general characteristics of the template, +including caching arguments, and optional lists of arguments +which the template expects when invoked. + +.. sourcecode:: mako + + <%page args="x, y, z='default'"/> + +Or a page tag that defines caching characteristics: + +.. sourcecode:: mako + + <%page cached="True" cache_type="memory"/> + +Currently, only one ``<%page>`` tag gets used per template, the +rest get ignored. While this will be improved in a future +release, for now make sure you have only one ``<%page>`` tag +defined in your template, else you may not get the results you +want. The details of what ``<%page>`` is used for are described +further in :ref:`namespaces_body` as well as :ref:`caching_toplevel`. + +``<%include>`` +-------------- + +A tag that is familiar from other template languages, ``%include`` +is a regular joe that just accepts a file argument and calls in +the rendered result of that file: + +.. sourcecode:: mako + + <%include file="header.html"/> + + hello world + + <%include file="footer.html"/> + +Include also accepts arguments which are available as ``<%page>`` arguments in the receiving template: + +.. sourcecode:: mako + + <%include file="toolbar.html" args="current_section='members', username='ed'"/> + +``<%def>`` +---------- + +The ``%def`` tag defines a Python function which contains a set +of content, that can be called at some other point in the +template. The basic idea is simple: + +.. sourcecode:: mako + + <%def name="myfunc(x)"> + this is myfunc, x is ${x} + + + ${myfunc(7)} + +The ``%def`` tag is a lot more powerful than a plain Python ``def``, as +the Mako compiler provides many extra services with ``%def`` that +you wouldn't normally have, such as the ability to export defs +as template "methods", automatic propagation of the current +:class:`.Context`, buffering/filtering/caching flags, and def calls +with content, which enable packages of defs to be sent as +arguments to other def calls (not as hard as it sounds). Get the +full deal on what ``%def`` can do in :ref:`defs_toplevel`. + +``<%block>`` +------------ + +``%block`` is a tag that is close to a ``%def``, +except executes itself immediately in its base-most scope, +and can also be anonymous (i.e. with no name): + +.. sourcecode:: mako + + <%block filter="h"> + some stuff. + + +Inspired by Jinja2 blocks, named blocks offer a syntactically pleasing way +to do inheritance: + +.. sourcecode:: mako + + + + <%block name="header"> +

      <%block name="title"/>

      + + ${self.body()} + + + +Blocks are introduced in :ref:`blocks` and further described in :ref:`inheritance_toplevel`. + +.. versionadded:: 0.4.1 + +``<%namespace>`` +---------------- + +``%namespace`` is Mako's equivalent of Python's ``import`` +statement. It allows access to all the rendering functions and +metadata of other template files, plain Python modules, as well +as locally defined "packages" of functions. + +.. sourcecode:: mako + + <%namespace file="functions.html" import="*"/> + +The underlying object generated by ``%namespace``, an instance of +:class:`.mako.runtime.Namespace`, is a central construct used in +templates to reference template-specific information such as the +current URI, inheritance structures, and other things that are +not as hard as they sound right here. Namespaces are described +in :ref:`namespaces_toplevel`. + +``<%inherit>`` +-------------- + +Inherit allows templates to arrange themselves in **inheritance +chains**. This is a concept familiar in many other template +languages. + +.. sourcecode:: mako + + <%inherit file="base.html"/> + +When using the ``%inherit`` tag, control is passed to the topmost +inherited template first, which then decides how to handle +calling areas of content from its inheriting templates. Mako +offers a lot of flexibility in this area, including dynamic +inheritance, content wrapping, and polymorphic method calls. +Check it out in :ref:`inheritance_toplevel`. + +``<%``\ nsname\ ``:``\ defname\ ``>`` +------------------------------------- + +Any user-defined "tag" can be created against +a namespace by using a tag with a name of the form +``<%:>``. The closed and open formats of such a +tag are equivalent to an inline expression and the ``<%call>`` +tag, respectively. + +.. sourcecode:: mako + + <%mynamespace:somedef param="some value"> + this is the body + + +To create custom tags which accept a body, see +:ref:`defs_with_content`. + +.. versionadded:: 0.2.3 + +``<%call>`` +----------- + +The call tag is the "classic" form of a user-defined tag, and is +roughly equivalent to the ``<%namespacename:defname>`` syntax +described above. This tag is also described in :ref:`defs_with_content`. + +``<%doc>`` +---------- + +The ``%doc`` tag handles multiline comments: + +.. sourcecode:: mako + + <%doc> + these are comments + more comments + + +Also the ``##`` symbol as the first non-space characters on a line can be used for single line comments. + +``<%text>`` +----------- + +This tag suspends the Mako lexer's normal parsing of Mako +template directives, and returns its entire body contents as +plain text. It is used pretty much to write documentation about +Mako: + +.. sourcecode:: mako + + <%text filter="h"> + heres some fake mako ${syntax} + <%def name="x()">${x} + + +Returning Early from a Template +=============================== + +Sometimes you want to stop processing a template or ``<%def>`` +method in the middle and just use the text you've accumulated so +far. You can use a ``return`` statement inside a Python +block to do that. + +.. sourcecode:: mako + + % if not len(records): + No records found. + <% return %> + % endif + +Or perhaps: + +.. sourcecode:: mako + + <% + if not len(records): + return + %> + diff --git a/lib/mako-0.7.2/doc/build/templates/base.mako b/lib/mako-0.7.2/doc/build/templates/base.mako new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/templates/base.mako @@ -0,0 +1,51 @@ + + + + +<%block name="head_title">Mako Templates for Python</%block> +<%block name="headers"> + + + + + + +
      + + + + +
      + + ${next.body()} +
      +<%block name="footer"> +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/build/templates/genindex.mako b/lib/mako-0.7.2/doc/build/templates/genindex.mako new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/templates/genindex.mako @@ -0,0 +1,77 @@ +<%inherit file="${context['layout']}"/> + +<%block name="show_title" filter="util.striptags"> + ${_('Index')} + + +

      ${_('Index')}

      + + % for i, (key, dummy) in enumerate(genindexentries): + ${i != 0 and '| ' or ''}${key} + % endfor + +
      + + % for i, (key, entries) in enumerate(genindexentries): +

      ${key}

      +
      +
      + <% + breakat = genindexcounts[i] // 2 + numcols = 1 + numitems = 0 + %> +% for entryname, (links, subitems) in entries: + +
      + % if links: + ${entryname|h} + % for unknown, link in links[1:]: + , [${i}] + % endfor + % else: + ${entryname|h} + % endif +
      + + % if subitems: +
      + % for subentryname, subentrylinks in subitems: +
      ${subentryname|h} + % for j, (unknown, link) in enumerate(subentrylinks[1:]): + [${j}] + % endfor +
      + % endfor +
      + % endif + + <% + numitems = numitems + 1 + len(subitems) + %> + % if numcols <2 and numitems > breakat: + <% + numcols = numcols + 1 + %> +
      + % endif + +% endfor +
      +
      +% endfor + +<%def name="sidebarrel()"> +% if split_index: +

      ${_('Index')}

      +

      + % for i, (key, dummy) in enumerate(genindexentries): + ${i > 0 and '| ' or ''} + ${key} + % endfor +

      + +

      ${_('Full index on one page')}

      +% endif + ${parent.sidebarrel()} + diff --git a/lib/mako-0.7.2/doc/build/templates/layout.mako b/lib/mako-0.7.2/doc/build/templates/layout.mako new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/templates/layout.mako @@ -0,0 +1,199 @@ +## coding: utf-8 +<%! + local_script_files = [] +%> +<%doc> + Structural elements are all prefixed with "docs-" + to prevent conflicts when the structure is integrated into the + main site. + + docs-container -> + docs-header -> + docs-search + docs-version-header + docs-top-navigation + docs-top-page-control + docs-navigation-banner + docs-body-container -> + docs-sidebar + docs-body + docs-bottom-navigation + docs-copyright + + +<%inherit file="base.mako"/> + +<% +withsidebar = bool(toc) and current_page_name != 'index' +%> + +<%block name="head_title"> + % if current_page_name != 'index': + ${capture(self.show_title) | util.striptags} — + % endif + ${docstitle|h} + + + +
      + +<%block name="headers"> + + + + + % for scriptfile in script_files + self.attr.local_script_files: + + % endfor + % if hasdoc('about'): + + % endif + + + % if hasdoc('copyright'): + + % endif + + % if parents: + + % endif + % if nexttopic: + + % endif + % if prevtopic: + + % endif + + +
      +

      ${docstitle|h}

      + + + +
      + Release: ${release} + +
      + +
      + +
      + + +
      + ${docstitle|h} + % if parents: + % for parent in parents: + ? ${parent['title']} + % endfor + % endif + % if current_page_name != 'index': + ? ${self.show_title()} + % endif + +

      + <%block name="show_title"> + ${title} + +

      +
      + +
      + +
      + +% if withsidebar: +
      +

      Table of Contents

      + ${toc} + + % if prevtopic: +

      Previous Topic

      +

      + ${prevtopic['title']} +

      + % endif + % if nexttopic: +

      Next Topic

      +

      + ${nexttopic['title']} +

      + % endif + +

      Quick Search

      +

      +

      +

      + +
      +% endif + +
      + ${next.body()} +
      + +
      + + + +
      diff --git a/lib/mako-0.7.2/doc/build/templates/page.mako b/lib/mako-0.7.2/doc/build/templates/page.mako new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/templates/page.mako @@ -0,0 +1,2 @@ +<%inherit file="${context['layout']}"/> +${body| util.strip_toplevel_anchors} \ No newline at end of file diff --git a/lib/mako-0.7.2/doc/build/templates/rtd_layout.mako b/lib/mako-0.7.2/doc/build/templates/rtd_layout.mako new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/templates/rtd_layout.mako @@ -0,0 +1,174 @@ + + +<%inherit file="/layout.mako"/> + +<% + newscript = [] + # strip out script files that RTD wants to provide + for script in script_files: + for token in ("jquery.js", "underscore.js", "doctools.js"): + if token in script: + break + else: + newscript.append(script) + script_files[:] = newscript +%> + +<%block name="headers"> + ${parent.headers()} + + + + + +##{% if using_theme %} +## +##{% endif %} + + + + + +${next.body()} + +<%block name="footer"> + ${parent.footer()} + +## Keep this here, so that the RTD logo doesn't stomp on the bottom of the theme. +
      +
      +
      + + + + + + +% if analytics_code: + + +% endif + + diff --git a/lib/mako-0.7.2/doc/build/templates/search.mako b/lib/mako-0.7.2/doc/build/templates/search.mako new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/templates/search.mako @@ -0,0 +1,25 @@ +<%inherit file="${context['layout']}"/> + +<%! + local_script_files = ['_static/searchtools.js'] +%> + +<%block name="show_title" filter="util.striptags"> + ${_('Search')} + + +
      +

      Enter Search Terms:

      + +
      + +
      + +<%block name="footer"> + ${parent.footer()} + + diff --git a/lib/mako-0.7.2/doc/build/unicode.rst b/lib/mako-0.7.2/doc/build/unicode.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/unicode.rst @@ -0,0 +1,345 @@ +.. _unicode_toplevel: + +=================== +The Unicode Chapter +=================== + +The Python language supports two ways of representing what we +know as "strings", i.e. series of characters. In Python 2, the +two types are ``string`` and ``unicode``, and in Python 3 they are +``bytes`` and ``string``. A key aspect of the Python 2 ``string`` and +Python 3 ``bytes`` types are that they contain no information +regarding what **encoding** the data is stored in. For this +reason they were commonly referred to as **byte strings** on +Python 2, and Python 3 makes this name more explicit. The +origins of this come from Python's background of being developed +before the Unicode standard was even available, back when +strings were C-style strings and were just that, a series of +bytes. Strings that had only values below 128 just happened to +be **ASCII** strings and were printable on the console, whereas +strings with values above 128 would produce all kinds of +graphical characters and bells. + +Contrast the "byte-string" type with the "unicode/string" type. +Objects of this latter type are created whenever you say something like +``u"hello world"`` (or in Python 3, just ``"hello world"``). In this +case, Python represents each character in the string internally +using multiple bytes per character (something similar to +UTF-16). What's important is that when using the +``unicode``/``string`` type to store strings, Python knows the +data's encoding; it's in its own internal format. Whereas when +using the ``string``/``bytes`` type, it does not. + +When Python 2 attempts to treat a byte-string as a string, which +means it's attempting to compare/parse its characters, to coerce +it into another encoding, or to decode it to a unicode object, +it has to guess what the encoding is. In this case, it will +pretty much always guess the encoding as ``ascii``... and if the +byte-string contains bytes above value 128, you'll get an error. +Python 3 eliminates much of this confusion by just raising an +error unconditionally if a byte-string is used in a +character-aware context. + +There is one operation that Python *can* do with a non-ASCII +byte-string, and it's a great source of confusion: it can dump the +byte-string straight out to a stream or a file, with nary a care +what the encoding is. To Python, this is pretty much like +dumping any other kind of binary data (like an image) to a +stream somewhere. In Python 2, it is common to see programs that +embed all kinds of international characters and encodings into +plain byte-strings (i.e. using ``"hello world"`` style literals) +can fly right through their run, sending reams of strings out to +wherever they are going, and the programmer, seeing the same +output as was expressed in the input, is now under the illusion +that his or her program is Unicode-compliant. In fact, their +program has no unicode awareness whatsoever, and similarly has +no ability to interact with libraries that *are* unicode aware. +Python 3 makes this much less likely by defaulting to unicode as +the storage format for strings. + +The "pass through encoded data" scheme is what template +languages like Cheetah and earlier versions of Myghty do by +default. Mako as of version 0.2 also supports this mode of +operation when using Python 2, using the ``disable_unicode=True`` +flag. However, when using Mako in its default mode of +unicode-aware, it requires explicitness when dealing with +non-ASCII encodings. Additionally, if you ever need to handle +unicode strings and other kinds of encoding conversions more +intelligently, the usage of raw byte-strings quickly becomes a +nightmare, since you are sending the Python interpreter +collections of bytes for which it can make no intelligent +decisions with regards to encoding. In Python 3 Mako only allows +usage of native, unicode strings. + +In normal Mako operation, all parsed template constructs and +output streams are handled internally as Python ``unicode`` +objects. It's only at the point of :meth:`~.Template.render` that this unicode +stream may be rendered into whatever the desired output encoding +is. The implication here is that the template developer must +:ensure that :ref:`the encoding of all non-ASCII templates is explicit +` (still required in Python 3), +that :ref:`all non-ASCII-encoded expressions are in one way or another +converted to unicode ` +(not much of a burden in Python 3), and that :ref:`the output stream of the +template is handled as a unicode stream being encoded to some +encoding ` (still required in Python 3). + +.. _set_template_file_encoding: + +Specifying the Encoding of a Template File +========================================== + +This is the most basic encoding-related setting, and it is +equivalent to Python's "magic encoding comment", as described in +`pep-0263 `_. Any +template that contains non-ASCII characters requires that this +comment be present so that Mako can decode to unicode (and also +make usage of Python's AST parsing services). Mako's lexer will +use this encoding in order to convert the template source into a +``unicode`` object before continuing its parsing: + +.. sourcecode:: mako + + ## -*- coding: utf-8 -*- + + Alors vous imaginez ma surprise, au lever du jour, quand + une dr?le de petite voix m?a r?veill?. Elle disait: + ? S?il vous pla?t? dessine-moi un mouton! ? + +For the picky, the regular expression used is derived from that +of the above mentioned pep: + +.. sourcecode:: python + + #.*coding[:=]\s*([-\w.]+).*\n + +The lexer will convert to unicode in all cases, so that if any +characters exist in the template that are outside of the +specified encoding (or the default of ``ascii``), the error will +be immediate. + +As an alternative, the template encoding can be specified +programmatically to either :class:`.Template` or :class:`.TemplateLookup` via +the ``input_encoding`` parameter: + +.. sourcecode:: python + + t = TemplateLookup(directories=['./'], input_encoding='utf-8') + +The above will assume all located templates specify ``utf-8`` +encoding, unless the template itself contains its own magic +encoding comment, which takes precedence. + +.. _handling_non_ascii_expressions: + +Handling Expressions +==================== + +The next area that encoding comes into play is in expression +constructs. By default, Mako's treatment of an expression like +this: + +.. sourcecode:: mako + + ${"hello world"} + +looks something like this: + +.. sourcecode:: python + + context.write(unicode("hello world")) + +In Python 3, it's just: + +.. sourcecode:: python + + context.write(str("hello world")) + +That is, **the output of all expressions is run through the +``unicode`` built-in**. This is the default setting, and can be +modified to expect various encodings. The ``unicode`` step serves +both the purpose of rendering non-string expressions into +strings (such as integers or objects which contain ``__str()__`` +methods), and to ensure that the final output stream is +constructed as a unicode object. The main implication of this is +that **any raw byte-strings that contain an encoding other than +ASCII must first be decoded to a Python unicode object**. It +means you can't say this in Python 2: + +.. sourcecode:: mako + + ${"voix m?a r?veill?."} ## error in Python 2! + +You must instead say this: + +.. sourcecode:: mako + + ${u"voix m?a r?veill?."} ## OK ! + +Similarly, if you are reading data from a file that is streaming +bytes, or returning data from some object that is returning a +Python byte-string containing a non-ASCII encoding, you have to +explicitly decode to unicode first, such as: + +.. sourcecode:: mako + + ${call_my_object().decode('utf-8')} + +Note that filehandles acquired by ``open()`` in Python 3 default +to returning "text", that is the decoding is done for you. See +Python 3's documentation for the ``open()`` built-in for details on +this. + +If you want a certain encoding applied to *all* expressions, +override the ``unicode`` builtin with the ``decode`` built-in at the +:class:`.Template` or :class:`.TemplateLookup` level: + +.. sourcecode:: python + + t = Template(templatetext, default_filters=['decode.utf8']) + +Note that the built-in ``decode`` object is slower than the +``unicode`` function, since unlike ``unicode`` it's not a Python +built-in, and it also checks the type of the incoming data to +determine if string conversion is needed first. + +The ``default_filters`` argument can be used to entirely customize +the filtering process of expressions. This argument is described +in :ref:`filtering_default_filters`. + +.. _defining_output_encoding: + +Defining Output Encoding +======================== + +Now that we have a template which produces a pure unicode output +stream, all the hard work is done. We can take the output and do +anything with it. + +As stated in the :doc:`"Usage" chapter `, both :class:`.Template` and +:class:`.TemplateLookup` accept ``output_encoding`` and ``encoding_errors`` +parameters which can be used to encode the output in any Python +supported codec: + +.. sourcecode:: python + + from mako.template import Template + from mako.lookup import TemplateLookup + + mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace') + + mytemplate = mylookup.get_template("foo.txt") + print mytemplate.render() + +:meth:`~.Template.render` will return a ``bytes`` object in Python 3 if an output +encoding is specified. By default it performs no encoding and +returns a native string. + +:meth:`~.Template.render_unicode` will return the template output as a Python +``unicode`` object (or ``string`` in Python 3): + +.. sourcecode:: python + + print mytemplate.render_unicode() + +The above method disgards the output encoding keyword argument; +you can encode yourself by saying: + +.. sourcecode:: python + + print mytemplate.render_unicode().encode('utf-8', 'replace') + +Buffer Selection +---------------- + +Mako does play some games with the style of buffering used +internally, to maximize performance. Since the buffer is by far +the most heavily used object in a render operation, it's +important! + +When calling :meth:`~.Template.render` on a template that does not specify any +output encoding (i.e. it's ``ascii``), Python's ``cStringIO`` module, +which cannot handle encoding of non-ASCII ``unicode`` objects +(even though it can send raw byte-strings through), is used for +buffering. Otherwise, a custom Mako class called +``FastEncodingBuffer`` is used, which essentially is a super +dumbed-down version of ``StringIO`` that gathers all strings into +a list and uses ``u''.join(elements)`` to produce the final output +-- it's markedly faster than ``StringIO``. + +.. _unicode_disabled: + +Saying to Heck with It: Disabling the Usage of Unicode Entirely +=============================================================== + +Some segments of Mako's userbase choose to make no usage of +Unicode whatsoever, and instead would prefer the "pass through" +approach; all string expressions in their templates return +encoded byte-strings, and they would like these strings to pass +right through. The only advantage to this approach is that +templates need not use ``u""`` for literal strings; there's an +arguable speed improvement as well since raw byte-strings +generally perform slightly faster than unicode objects in +Python. For these users, assuming they're sticking with Python +2, they can hit the ``disable_unicode=True`` flag as so: + +.. sourcecode:: python + + # -*- encoding:utf-8 -*- + from mako.template import Template + + t = Template("dr?le de petite voix m?a r?veill?.", disable_unicode=True, input_encoding='utf-8') + print t.code + +The ``disable_unicode`` mode is strictly a Python 2 thing. It is +not supported at all in Python 3. + +The generated module source code will contain elements like +these: + +.. sourcecode:: python + + # -*- encoding:utf-8 -*- + # ...more generated code ... + + def render_body(context,**pageargs): + context.caller_stack.push_frame() + try: + __M_locals = dict(pageargs=pageargs) + # SOURCE LINE 1 + context.write('dr\xc3\xb4le de petite voix m\xe2\x80\x99a r\xc3\xa9veill\xc3\xa9.') + return '' + finally: + context.caller_stack.pop_frame() + +Where above that the string literal used within :meth:`.Context.write` +is a regular byte-string. + +When ``disable_unicode=True`` is turned on, the ``default_filters`` +argument which normally defaults to ``["unicode"]`` now defaults +to ``["str"]`` instead. Setting ``default_filters`` to the empty list +``[]`` can remove the overhead of the ``str`` call. Also, in this +mode you **cannot** safely call :meth:`~.Template.render_unicode` -- you'll get +unicode/decode errors. + +The ``h`` filter (HTML escape) uses a less performant pure Python +escape function in non-unicode mode. This because +MarkupSafe only supports Python unicode objects for non-ASCII +strings. + +.. versionchanged:: 0.3.4 + In prior versions, it used ``cgi.escape()``, which has been replaced + with a function that also escapes single quotes. + +Rules for using ``disable_unicode=True`` +---------------------------------------- + +* Don't use this mode unless you really, really want to and you + absolutely understand what you're doing. +* Don't use this option just because you don't want to learn to + use Unicode properly; we aren't supporting user issues in this + mode of operation. We will however offer generous help for the + vast majority of users who stick to the Unicode program. +* Python 3 is unicode by default, and the flag is not available + when running on Python 3. + diff --git a/lib/mako-0.7.2/doc/build/usage.rst b/lib/mako-0.7.2/doc/build/usage.rst new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/build/usage.rst @@ -0,0 +1,520 @@ +.. _usage_toplevel: + +===== +Usage +===== + +Basic Usage +=========== + +This section describes the Python API for Mako templates. If you +are using Mako within a web framework such as Pylons, the work +of integrating Mako's API is already done for you, in which case +you can skip to the next section, :ref:`syntax_toplevel`. + +The most basic way to create a template and render it is through +the :class:`.Template` class: + +.. sourcecode:: python + + from mako.template import Template + + mytemplate = Template("hello world!") + print mytemplate.render() + +Above, the text argument to :class:`.Template` is **compiled** into a +Python module representation. This module contains a function +called ``render_body()``, which produces the output of the +template. When ``mytemplate.render()`` is called, Mako sets up a +runtime environment for the template and calls the +``render_body()`` function, capturing the output into a buffer and +returning its string contents. + + +The code inside the ``render_body()`` function has access to a +namespace of variables. You can specify these variables by +sending them as additional keyword arguments to the :meth:`~.Template.render` +method: + +.. sourcecode:: python + + from mako.template import Template + + mytemplate = Template("hello, ${name}!") + print mytemplate.render(name="jack") + +The :meth:`~.Template.render` method calls upon Mako to create a +:class:`.Context` object, which stores all the variable names accessible +to the template and also stores a buffer used to capture output. +You can create this :class:`.Context` yourself and have the template +render with it, using the :meth:`~.Template.render_context` method: + +.. sourcecode:: python + + from mako.template import Template + from mako.runtime import Context + from StringIO import StringIO + + mytemplate = Template("hello, ${name}!") + buf = StringIO() + ctx = Context(buf, name="jack") + mytemplate.render_context(ctx) + print buf.getvalue() + +Using File-Based Templates +========================== + +A :class:`.Template` can also load its template source code from a file, +using the ``filename`` keyword argument: + +.. sourcecode:: python + + from mako.template import Template + + mytemplate = Template(filename='/docs/mytmpl.txt') + print mytemplate.render() + +For improved performance, a :class:`.Template` which is loaded from a +file can also cache the source code to its generated module on +the filesystem as a regular Python module file (i.e. a ``.py`` +file). To do this, just add the ``module_directory`` argument to +the template: + +.. sourcecode:: python + + from mako.template import Template + + mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules') + print mytemplate.render() + +When the above code is rendered, a file +``/tmp/mako_modules/docs/mytmpl.txt.py`` is created containing the +source code for the module. The next time a :class:`.Template` with the +same arguments is created, this module file will be +automatically re-used. + +.. _usage_templatelookup: + +Using ``TemplateLookup`` +======================== + +All of the examples thus far have dealt with the usage of a +single :class:`.Template` object. If the code within those templates +tries to locate another template resource, it will need some way +to find them, using simple URI strings. For this need, the +resolution of other templates from within a template is +accomplished by the :class:`.TemplateLookup` class. This class is +constructed given a list of directories in which to search for +templates, as well as keyword arguments that will be passed to +the :class:`.Template` objects it creates: + +.. sourcecode:: python + + from mako.template import Template + from mako.lookup import TemplateLookup + + mylookup = TemplateLookup(directories=['/docs']) + mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup) + +Above, we created a textual template which includes the file +``"header.txt"``. In order for it to have somewhere to look for +``"header.txt"``, we passed a :class:`.TemplateLookup` object to it, which +will search in the directory ``/docs`` for the file ``"header.txt"``. + +Usually, an application will store most or all of its templates +as text files on the filesystem. So far, all of our examples +have been a little bit contrived in order to illustrate the +basic concepts. But a real application would get most or all of +its templates directly from the :class:`.TemplateLookup`, using the +aptly named :meth:`~.TemplateLookup.get_template` method, which accepts the URI of the +desired template: + +.. sourcecode:: python + + from mako.template import Template + from mako.lookup import TemplateLookup + + mylookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules') + + def serve_template(templatename, **kwargs): + mytemplate = mylookup.get_template(templatename) + print mytemplate.render(**kwargs) + +In the example above, we create a :class:`.TemplateLookup` which will +look for templates in the ``/docs`` directory, and will store +generated module files in the ``/tmp/mako_modules`` directory. The +lookup locates templates by appending the given URI to each of +its search directories; so if you gave it a URI of +``/etc/beans/info.txt``, it would search for the file +``/docs/etc/beans/info.txt``, else raise a :class:`.TopLevelNotFound` +exception, which is a custom Mako exception. + +When the lookup locates templates, it will also assign a ``uri`` +property to the :class:`.Template` which is the URI passed to the +:meth:`~.TemplateLookup.get_template()` call. :class:`.Template` uses this URI to calculate the +name of its module file. So in the above example, a +``templatename`` argument of ``/etc/beans/info.txt`` will create a +module file ``/tmp/mako_modules/etc/beans/info.txt.py``. + +Setting the Collection Size +--------------------------- + +The :class:`.TemplateLookup` also serves the important need of caching a +fixed set of templates in memory at a given time, so that +successive URI lookups do not result in full template +compilations and/or module reloads on each request. By default, +the :class:`.TemplateLookup` size is unbounded. You can specify a fixed +size using the ``collection_size`` argument: + +.. sourcecode:: python + + mylookup = TemplateLookup(directories=['/docs'], + module_directory='/tmp/mako_modules', collection_size=500) + +The above lookup will continue to load templates into memory +until it reaches a count of around 500. At that point, it will +clean out a certain percentage of templates using a least +recently used scheme. + +Setting Filesystem Checks +------------------------- + +Another important flag on :class:`.TemplateLookup` is +``filesystem_checks``. This defaults to ``True``, and says that each +time a template is returned by the :meth:`~.TemplateLookup.get_template()` method, the +revision time of the original template file is checked against +the last time the template was loaded, and if the file is newer +will reload its contents and recompile the template. On a +production system, setting ``filesystem_checks`` to ``False`` can +afford a small to moderate performance increase (depending on +the type of filesystem used). + +.. _usage_unicode: + +Using Unicode and Encoding +========================== + +Both :class:`.Template` and :class:`.TemplateLookup` accept ``output_encoding`` +and ``encoding_errors`` parameters which can be used to encode the +output in any Python supported codec: + +.. sourcecode:: python + + from mako.template import Template + from mako.lookup import TemplateLookup + + mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace') + + mytemplate = mylookup.get_template("foo.txt") + print mytemplate.render() + +When using Python 3, the :meth:`~.Template.render` method will return a ``bytes`` +object, **if** ``output_encoding`` is set. Otherwise it returns a +``string``. + +Additionally, the :meth:`~.Template.render_unicode()` method exists which will +return the template output as a Python ``unicode`` object, or in +Python 3 a ``string``: + +.. sourcecode:: python + + print mytemplate.render_unicode() + +The above method disregards the output encoding keyword +argument; you can encode yourself by saying: + +.. sourcecode:: python + + print mytemplate.render_unicode().encode('utf-8', 'replace') + +Note that Mako's ability to return data in any encoding and/or +``unicode`` implies that the underlying output stream of the +template is a Python unicode object. This behavior is described +fully in :ref:`unicode_toplevel`. + +.. _handling_exceptions: + +Handling Exceptions +=================== + +Template exceptions can occur in two distinct places. One is +when you **lookup, parse and compile** the template, the other +is when you **run** the template. Within the running of a +template, exceptions are thrown normally from whatever Python +code originated the issue. Mako has its own set of exception +classes which mostly apply to the lookup and lexer/compiler +stages of template construction. Mako provides some library +routines that can be used to help provide Mako-specific +information about any exception's stack trace, as well as +formatting the exception within textual or HTML format. In all +cases, the main value of these handlers is that of converting +Python filenames, line numbers, and code samples into Mako +template filenames, line numbers, and code samples. All lines +within a stack trace which correspond to a Mako template module +will be converted to be against the originating template file. + +To format exception traces, the :func:`.text_error_template` and +:func:`.html_error_template` functions are provided. They make usage of +``sys.exc_info()`` to get at the most recently thrown exception. +Usage of these handlers usually looks like: + +.. sourcecode:: python + + from mako import exceptions + + try: + template = lookup.get_template(uri) + print template.render() + except: + print exceptions.text_error_template().render() + +Or for the HTML render function: + +.. sourcecode:: python + + from mako import exceptions + + try: + template = lookup.get_template(uri) + print template.render() + except: + print exceptions.html_error_template().render() + +The :func:`.html_error_template` template accepts two options: +specifying ``full=False`` causes only a section of an HTML +document to be rendered. Specifying ``css=False`` will disable the +default stylesheet from being rendered. + +E.g.: + +.. sourcecode:: python + + print exceptions.html_error_template().render(full=False) + +The HTML render function is also available built-in to +:class:`.Template` using the ``format_exceptions`` flag. In this case, any +exceptions raised within the **render** stage of the template +will result in the output being substituted with the output of +:func:`.html_error_template`: + +.. sourcecode:: python + + template = Template(filename="/foo/bar", format_exceptions=True) + print template.render() + +Note that the compile stage of the above template occurs when +you construct the :class:`.Template` itself, and no output stream is +defined. Therefore exceptions which occur within the +lookup/parse/compile stage will not be handled and will +propagate normally. While the pre-render traceback usually will +not include any Mako-specific lines anyway, it will mean that +exceptions which occur previous to rendering and those which +occur within rendering will be handled differently... so the +``try``/``except`` patterns described previously are probably of more +general use. + +The underlying object used by the error template functions is +the :class:`.RichTraceback` object. This object can also be used +directly to provide custom error views. Here's an example usage +which describes its general API: + +.. sourcecode:: python + + from mako.exceptions import RichTraceback + + try: + template = lookup.get_template(uri) + print template.render() + except: + traceback = RichTraceback() + for (filename, lineno, function, line) in traceback.traceback: + print "File %s, line %s, in %s" % (filename, lineno, function) + print line, "\n" + print "%s: %s" % (str(traceback.error.__class__.__name__), traceback.error) + +Common Framework Integrations +============================= + +The Mako distribution includes a little bit of helper code for +the purpose of using Mako in some popular web framework +scenarios. This is a brief description of what's included. + +WSGI +---- + +A sample WSGI application is included in the distribution in the +file ``examples/wsgi/run_wsgi.py``. This runner is set up to pull +files from a `templates` as well as an `htdocs` directory and +includes a rudimental two-file layout. The WSGI runner acts as a +fully functional standalone web server, using ``wsgiutils`` to run +itself, and propagates GET and POST arguments from the request +into the :class:`.Context`, can serve images, CSS files and other kinds +of files, and also displays errors using Mako's included +exception-handling utilities. + +Pygments +-------- + +A `Pygments `_-compatible syntax +highlighting module is included under :mod:`mako.ext.pygmentplugin`. +This module is used in the generation of Mako documentation and +also contains various `setuptools` entry points under the heading +``pygments.lexers``, including ``mako``, ``html+mako``, ``xml+mako`` +(see the ``setup.py`` file for all the entry points). + +Babel +----- + +Mako provides support for extracting `gettext` messages from +templates via a `Babel`_ extractor +entry point under ``mako.ext.babelplugin``. + +`Gettext` messages are extracted from all Python code sections, +including those of control lines and expressions embedded +in tags. + +`Translator +comments `_ +may also be extracted from Mako templates when a comment tag is +specified to `Babel`_ (such as with +the ``-c`` option). + +For example, a project ``"myproj"`` contains the following Mako +template at ``myproj/myproj/templates/name.html``: + +.. sourcecode:: mako + +
      + Name: + ## TRANSLATORS: This is a proper name. See the gettext + ## manual, section Names. + ${_('Francois Pinard')} +
      + +To extract gettext messages from this template the project needs +a Mako section in its `Babel Extraction Method Mapping +file `_ +(typically located at ``myproj/babel.cfg``): + +.. sourcecode:: cfg + + # Extraction from Python source files + + [python: myproj/**.py] + + # Extraction from Mako templates + + [mako: myproj/templates/**.html] + input_encoding = utf-8 + +The Mako extractor supports an optional ``input_encoding`` +parameter specifying the encoding of the templates (identical to +:class:`.Template`/:class:`.TemplateLookup`'s ``input_encoding`` parameter). + +Invoking `Babel`_'s extractor at the +command line in the project's root directory: + +.. sourcecode:: sh + + myproj$ pybabel extract -F babel.cfg -c "TRANSLATORS:" . + +will output a `gettext` catalog to `stdout` including the following: + +.. sourcecode:: pot + + #. TRANSLATORS: This is a proper name. See the gettext + #. manual, section Names. + #: myproj/templates/name.html:5 + msgid "Francois Pinard" + msgstr "" + +This is only a basic example: +`Babel`_ can be invoked from ``setup.py`` +and its command line options specified in the accompanying +``setup.cfg`` via `Babel Distutils/Setuptools +Integration `_. + +Comments must immediately precede a `gettext` message to be +extracted. In the following case the ``TRANSLATORS:`` comment would +not have been extracted: + +.. sourcecode:: mako + +
      + ## TRANSLATORS: This is a proper name. See the gettext + ## manual, section Names. + Name: ${_('Francois Pinard')} +
      + +See the `Babel User +Guide `_ +for more information. + +.. _babel: http://babel.edgewall.org/ + + +API Reference +============= + +.. autoclass:: mako.template.Template + :show-inheritance: + :members: + +.. autoclass:: mako.template.DefTemplate + :show-inheritance: + :members: + +.. autoclass:: mako.lookup.TemplateCollection + :show-inheritance: + :members: + +.. autoclass:: mako.lookup.TemplateLookup + :show-inheritance: + :members: + +.. autoclass:: mako.exceptions.RichTraceback + :show-inheritance: + + .. py:attribute:: error + + the exception instance. + + .. py:attribute:: message + + the exception error message as unicode. + + .. py:attribute:: source + + source code of the file where the error occurred. + If the error occurred within a compiled template, + this is the template source. + + .. py:attribute:: lineno + + line number where the error occurred. If the error + occurred within a compiled template, the line number + is adjusted to that of the template source. + + .. py:attribute:: records + + a list of 8-tuples containing the original + python traceback elements, plus the + filename, line number, source line, and full template source + for the traceline mapped back to its originating source + template, if any for that traceline (else the fields are ``None``). + + .. py:attribute:: reverse_records + + the list of records in reverse + traceback -- a list of 4-tuples, in the same format as a regular + python traceback, with template-corresponding + traceback records replacing the originals. + + .. py:attribute:: reverse_traceback + + the traceback list in reverse. + +.. autofunction:: mako.exceptions.html_error_template + +.. autofunction:: mako.exceptions.text_error_template + diff --git a/lib/mako-0.7.2/doc/caching.html b/lib/mako-0.7.2/doc/caching.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/caching.html @@ -0,0 +1,777 @@ + + + + + + + Caching + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Caching + + +

      + + Caching + +

      +
      + +
      + +
      + + + +
      + +
      +

      Caching?

      +

      Any template or component can be cached using the cache +argument to the <%page>, <%def> or <%block> directives:

      +
      <%page cached="True"/>
      +
      +template text
      +
      +
      +

      The above template, after being executed the first time, will +store its content within a cache that by default is scoped +within memory. Subsequent calls to the template’s render() +method will return content directly from the cache. When the +Template object itself falls out of scope, its corresponding +cache is garbage collected along with the template.

      +

      By default, caching requires that the Beaker package be installed on the +system, however the mechanism of caching can be customized to use +any third party or user defined system – see Cache Plugins.

      +

      In addition to being available on the <%page> tag, the caching flag and all +its options can be used with the <%def> tag as well:

      +
      <%def name="mycomp" cached="True" cache_timeout="60">
      +    other text
      +</%def>
      +
      +
      +

      ... and equivalently with the <%block> tag, anonymous or named:

      +
      <%block cached="True" cache_timeout="60">
      +    other text
      +</%block>
      +
      +
      +
      +

      Cache Arguments?

      +

      Mako has two cache arguments available on tags that are +available in all cases. The rest of the arguments +available are specific to a backend.

      +

      The two generic tags arguments are:

      +
        +
      • cached="True" - enable caching for this <%page>, +<%def>, or <%block>.

        +
      • +
      • cache_key - the “key” used to uniquely identify this content +in the cache. Usually, this key is chosen automatically +based on the name of the rendering callable (i.e. body +when used in <%page>, the name of the def when using <%def>, +the explicit or internally-generated name when using <%block>). +Using the cache_key parameter, the key can be overridden +using a fixed or programmatically generated value.

        +

        For example, here’s a page +that caches any page which inherits from it, based on the +filename of the calling template:

        +
        <%page cached="True" cache_key="${self.filename}"/>
        +
        +${next.body()}
        +
        +## rest of template
        +
        +
        +
      • +
      +

      On a Template or TemplateLookup, the +caching can be configured using these arguments:

      +
        +
      • cache_enabled - Setting this +to False will disable all caching functionality +when the template renders. Defaults to True. +e.g.:

        +
        lookup = TemplateLookup(
        +                directories='/path/to/templates',
        +                cache_enabled = False
        +                )
        +
        +
        +
      • +
      • cache_impl - The string name of the cache backend +to use. This defaults to 'beaker', which has historically +been the only cache backend supported by Mako.

        +

        +New in version 0.6.0.

        +

        For example, here’s how to use the upcoming +dogpile.cache +backend:

        +
        lookup = TemplateLookup(
        +                directories='/path/to/templates',
        +                cache_impl = 'dogpile.cache',
        +                cache_args = {'regions':my_dogpile_regions}
        +                )
        +
        +
        +
      • +
      • cache_args - A dictionary of cache parameters that +will be consumed by the cache backend. See +Using the Beaker Cache Backend for examples.

        +

        +New in version 0.6.0.

        +
      • +
      +
      +

      Backend-Specific Cache Arguments?

      +

      The <%page>, <%def>, and <%block> tags +accept any named argument that starts with the prefix "cache_". +Those arguments are then packaged up and passed along to the +underlying caching implementation, minus the "cache_" prefix.

      +

      The actual arguments understood are determined by the backend.

      + +
      +
      +

      Using the Beaker Cache Backend?

      +

      When using Beaker, new implementations will want to make usage +of cache regions so that cache configurations can be maintained +externally to templates. These configurations live under +named “regions” that can be referred to within templates themselves.

      +

      +New in version 0.6.0: Support for Beaker cache regions.

      +

      For example, suppose we would like two regions. One is a “short term” +region that will store content in a memory-based dictionary, +expiring after 60 seconds. The other is a Memcached region, +where values should expire in five minutes. To configure +our TemplateLookup, first we get a handle to a +beaker.cache.CacheManager:

      +
      from beaker.cache import CacheManager
      +
      +manager = CacheManager(cache_regions={
      +    'short_term':{
      +        'type': 'memory',
      +        'expire': 60
      +    },
      +    'long_term':{
      +        'type': 'ext:memcached',
      +        'url': '127.0.0.1:11211',
      +        'expire': 300
      +    }
      +})
      +
      +lookup = TemplateLookup(
      +                directories=['/path/to/templates'],
      +                module_directory='/path/to/modules',
      +                cache_impl='beaker',
      +                cache_args={
      +                    'manager':manager
      +                }
      +        )
      +
      +
      +

      Our templates can then opt to cache data in one of either region, +using the cache_region argument. Such as using short_term +at the <%page> level:

      +
      <%page cached="True" cache_region="short_term">
      +
      +## ...
      +
      +
      +

      Or, long_term at the <%block> level:

      +
      <%block name="header" cached="True" cache_region="long_term">
      +    other text
      +</%block>
      +
      +
      +

      The Beaker backend also works without regions. There are a +variety of arguments that can be passed to the cache_args +dictionary, which are also allowable in templates via the +<%page>, <%block>, +and <%def> tags specific to those sections. The values +given override those specified at the TemplateLookup +or Template level.

      +

      With the possible exception +of cache_timeout, these arguments are probably better off +staying at the template configuration level. Each argument +specified as cache_XYZ in a template tag is specified +without the cache_ prefix in the cache_args dictionary:

      +
        +
      • cache_timeout - number of seconds in which to invalidate the +cached data. After this timeout, the content is re-generated +on the next call. Available as timeout in the cache_args +dictionary.
      • +
      • cache_type - type of caching. 'memory', 'file', 'dbm', or +'ext:memcached' (note that the string memcached is +also accepted by the dogpile.cache Mako plugin, though not by Beaker itself). +Available as type in the cache_args dictionary.
      • +
      • cache_url - (only used for memcached but required) a single +IP address or a semi-colon separated list of IP address of +memcache servers to use. Available as url in the cache_args +dictionary.
      • +
      • cache_dir - in the case of the 'file' and 'dbm' cache types, +this is the filesystem directory with which to store data +files. If this option is not present, the value of +module_directory is used (i.e. the directory where compiled +template modules are stored). If neither option is available +an exception is thrown. Available as dir in the +cache_args dictionary.
      • +
      +
      +
      +

      Using the dogpile.cache Backend?

      +

      dogpile.cache is a new replacement for Beaker. It provides +a modernized, slimmed down interface and is generally easier to use +than Beaker. As of this writing it has not yet been released. dogpile.cache +includes its own Mako cache plugin – see dogpile.cache.plugins.mako_cache in the +dogpile.cache documentation.

      +
      +
      +
      +

      Programmatic Cache Access?

      +

      The Template, as well as any template-derived Namespace, has +an accessor called cache which returns the Cache object +for that template. This object is a facade on top of the underlying +CacheImpl object, and provides some very rudimental +capabilities, such as the ability to get and put arbitrary +values:

      +
      <%
      +    local.cache.set("somekey", type="memory", "somevalue")
      +%>
      +
      +
      +

      Above, the cache associated with the local namespace is +accessed and a key is placed within a memory cache.

      +

      More commonly, the cache object is used to invalidate cached +sections programmatically:

      +
      template = lookup.get_template('/sometemplate.html')
      +
      +# invalidate the "body" of the template
      +template.cache.invalidate_body()
      +
      +# invalidate an individual def
      +template.cache.invalidate_def('somedef')
      +
      +# invalidate an arbitrary key
      +template.cache.invalidate('somekey')
      +
      +
      +

      You can access any special method or attribute of the CacheImpl +itself using the impl attribute:

      +
      template.cache.impl.do_something_special()
      +
      +
      +

      Note that using implementation-specific methods will mean you can’t +swap in a different kind of CacheImpl implementation at a +later time.

      +
      +
      +

      Cache Plugins?

      +

      The mechanism used by caching can be plugged in +using a CacheImpl subclass. This class implements +the rudimental methods Mako needs to implement the caching +API. Mako includes the BeakerCacheImpl class to +provide the default implementation. A CacheImpl class +is acquired by Mako using a pkg_resources entrypoint, using +the name given as the cache_impl argument to Template +or TemplateLookup. This entry point can be +installed via the standard setuptools/setup() procedure, underneath +the EntryPoint group named "mako.cache". It can also be +installed at runtime via a convenience installer register_plugin() +which accomplishes essentially the same task.

      +

      An example plugin that implements a local dictionary cache:

      +
      from mako.cache import Cacheimpl, register_plugin
      +
      +class SimpleCacheImpl(CacheImpl):
      +    def __init__(self, cache):
      +        super(SimpleCacheImpl, self).__init__(cache)
      +        self._cache = {}
      +
      +    def get_or_create(self, key, creation_function, **kw):
      +        if key in self._cache:
      +            return self._cache[key]
      +        else:
      +            self._cache[key] = value = creation_function()
      +            return value
      +
      +    def set(self, key, value, **kwargs):
      +        self._cache[key] = value
      +
      +    def get(self, key, **kwargs):
      +        return self._cache.get(key)
      +
      +    def invalidate(self, key, **kwargs):
      +        self._cache.pop(key, None)
      +
      +# optional - register the class locally
      +register_plugin("simple", __name__, "SimpleCacheImpl")
      +
      +
      +

      Enabling the above plugin in a template would look like:

      +
      t = Template("mytemplate",
      +             file="mytemplate.html",
      +             cache_impl='simple')
      +
      +
      +
      +

      Guidelines for Writing Cache Plugins?

      +
        +
      • The CacheImpl is created on a per-Template basis. The +class should ensure that only data for the parent Template is +persisted or returned by the cache methods. The actual Template +is available via the self.cache.template attribute. The self.cache.id +attribute, which is essentially the unique modulename of the template, is +a good value to use in order to represent a unique namespace of keys specific +to the template.
      • +
      • Templates only use the CacheImpl.get_or_create() method +in an implicit fashion. The CacheImpl.set(), +CacheImpl.get(), and CacheImpl.invalidate() methods are +only used in response to direct programmatic access to the corresponding +methods on the Cache object.
      • +
      • CacheImpl will be accessed in a multithreaded fashion if the +Template itself is used multithreaded. Care should be taken +to ensure caching implementations are threadsafe.
      • +
      • A library like Dogpile, which +is a minimal locking system derived from Beaker, can be used to help +implement the CacheImpl.get_or_create() method in a threadsafe +way that can maximize effectiveness across multiple threads as well +as processes. CacheImpl.get_or_create() is the +key method used by templates.
      • +
      • All arguments passed to **kw come directly from the parameters +inside the <%def>, <%block>, or <%page> tags directly, +minus the "cache_" prefix, as strings, with the exception of +the argument cache_timeout, which is passed to the plugin +as the name timeout with the value converted to an integer. +Arguments present in cache_args on Template or +TemplateLookup are passed directly, but are superseded +by those present in the most specific template tag.
      • +
      • The directory where Template places module files can +be acquired using the accessor self.cache.template.module_directory. +This directory can be a good place to throw cache-related work +files, underneath a prefix like _my_cache_work so that name +conflicts with generated modules don’t occur.
      • +
      +
      +
      +
      +

      API Reference?

      +
      +
      +class mako.cache.Cache(template, *args)?
      +

      Bases: object

      +

      Represents a data content cache made available to the module +space of a specific Template object.

      +

      +New in version 0.6: Cache by itself is mostly a +container for a CacheImpl object, which implements +a fixed API to provide caching services; specific subclasses exist to +implement different +caching strategies. Mako includes a backend that works with +the Beaker caching system. Beaker itself then supports +a number of backends (i.e. file, memory, memcached, etc.)

      +

      The construction of a Cache is part of the mechanics +of a Template, and programmatic access to this +cache is typically via the Template.cache attribute.

      +
      +
      +get(key, **kw)?
      +

      Retrieve a value from the cache.

      + +++ + + + +
      Parameters:
        +
      • key – the value’s key.
      • +
      • **kw – cache configuration arguments. The +backend is configured using these arguments upon first request. +Subsequent requests that use the same series of configuration +values will use that same backend.
      • +
      +
      +
      + +
      +
      +get_or_create(key, creation_function, **kw)?
      +

      Retrieve a value from the cache, using the given creation function +to generate a new value.

      +
      + +
      +
      +id = None?
      +

      Return the ‘id’ that identifies this cache.

      +

      This is a value that should be globally unique to the +Template associated with this cache, and can +be used by a caching system to name a local container +for data specific to this template.

      +
      + +
      +
      +impl = None?
      +

      Provide the CacheImpl in use by this Cache.

      +

      This accessor allows a CacheImpl with additional +methods beyond that of Cache to be used programmatically.

      +
      + +
      +
      +invalidate(key, **kw)?
      +

      Invalidate a value in the cache.

      + +++ + + + +
      Parameters:
        +
      • key – the value’s key.
      • +
      • **kw – cache configuration arguments. The +backend is configured using these arguments upon first request. +Subsequent requests that use the same series of configuration +values will use that same backend.
      • +
      +
      +
      + +
      +
      +invalidate_body()?
      +

      Invalidate the cached content of the “body” method for this +template.

      +
      + +
      +
      +invalidate_closure(name)?
      +

      Invalidate a nested <%def> within this template.

      +

      Caching of nested defs is a blunt tool as there is no +management of scope – nested defs that use cache tags +need to have names unique of all other nested defs in the +template, else their content will be overwritten by +each other.

      +
      + +
      +
      +invalidate_def(name)?
      +

      Invalidate the cached content of a particular <%def> within this +template.

      +
      + +
      +
      +put(key, value, **kw)?
      +

      A synonym for Cache.set().

      +

      This is here for backwards compatibility.

      +
      + +
      +
      +set(key, value, **kw)?
      +

      Place a value in the cache.

      + +++ + + + +
      Parameters:
        +
      • key – the value’s key.
      • +
      • value – the value.
      • +
      • **kw – cache configuration arguments.
      • +
      +
      +
      + +
      +
      +starttime = None?
      +

      Epochal time value for when the owning Template was +first compiled.

      +

      A cache implementation may wish to invalidate data earlier than +this timestamp; this has the effect of the cache for a specific +Template starting clean any time the Template +is recompiled, such as when the original template file changed on +the filesystem.

      +
      + +
      + +
      +
      +class mako.cache.CacheImpl(cache)?
      +

      Bases: object

      +

      Provide a cache implementation for use by Cache.

      +
      +
      +get(key, **kw)?
      +

      Retrieve a value from the cache.

      + +++ + + + +
      Parameters:
        +
      • key – the value’s key.
      • +
      • **kw – cache configuration arguments.
      • +
      +
      +
      + +
      +
      +get_or_create(key, creation_function, **kw)?
      +

      Retrieve a value from the cache, using the given creation function +to generate a new value.

      +

      This function must return a value, either from +the cache, or via the given creation function. +If the creation function is called, the newly +created value should be populated into the cache +under the given key before being returned.

      + +++ + + + +
      Parameters:
        +
      • key – the value’s key.
      • +
      • creation_function – function that when called generates +a new value.
      • +
      • **kw – cache configuration arguments.
      • +
      +
      +
      + +
      +
      +invalidate(key, **kw)?
      +

      Invalidate a value in the cache.

      + +++ + + + +
      Parameters:
        +
      • key – the value’s key.
      • +
      • **kw – cache configuration arguments.
      • +
      +
      +
      + +
      +
      +pass_context = False?
      +

      If True, the Context will be passed to +get_or_create as the name 'context'.

      +
      + +
      +
      +set(key, value, **kw)?
      +

      Place a value in the cache.

      + +++ + + + +
      Parameters:
        +
      • key – the value’s key.
      • +
      • value – the value.
      • +
      • **kw – cache configuration arguments.
      • +
      +
      +
      + +
      + +
      +
      +mako.cache.register_plugin(self, name, modulepath, objname)?
      +
      + +
      +
      +class mako.ext.beaker_cache.BeakerCacheImpl(cache)?
      +

      Bases: mako.cache.CacheImpl

      +

      A CacheImpl provided for the Beaker caching system.

      +

      This plugin is used by default, based on the default +value of 'beaker' for the cache_impl parameter of the +Template or TemplateLookup classes.

      +
      + +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/defs.html b/lib/mako-0.7.2/doc/defs.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/defs.html @@ -0,0 +1,726 @@ + + + + + + + Defs and Blocks + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Defs and Blocks + + +

      + + Defs and Blocks + +

      +
      + +
      + +
      + + + +
      + +
      +

      Defs and Blocks?

      +

      <%def> and <%block> are two tags that both demarcate any block of text +and/or code. They both exist within generated Python as a callable function, +i.e., a Python def. They differ in their scope and calling semantics. +Whereas <%def> provides a construct that is very much like a named Python +def, the <%block> is more layout oriented.

      +
      +

      Using Defs?

      +

      The <%def> tag requires a name attribute, where the name references +a Python function signature:

      +
      <%def name="hello()">
      +    hello world
      +</%def>
      +
      +
      +

      To invoke the <%def>, it is normally called as an expression:

      +
      the def:  ${hello()}
      +
      +
      +

      If the <%def> is not nested inside of another <%def>, +it’s known as a top level def and can be accessed anywhere in +the template, including above where it was defined.

      +

      All defs, top level or not, have access to the current +contextual namespace in exactly the same way their containing +template does. Suppose the template below is executed with the +variables username and accountdata inside the context:

      +
      Hello there ${username}, how are ya.  Lets see what your account says:
      +
      +${account()}
      +
      +<%def name="account()">
      +    Account for ${username}:<br/>
      +
      +    % for row in accountdata:
      +        Value: ${row}<br/>
      +    % endfor
      +</%def>
      +
      +
      +

      The username and accountdata variables are present +within the main template body as well as the body of the +account() def.

      +

      Since defs are just Python functions, you can define and pass +arguments to them as well:

      +
      ${account(accountname='john')}
      +
      +<%def name="account(accountname, type='regular')">
      +    account name: ${accountname}, type: ${type}
      +</%def>
      +
      +
      +

      When you declare an argument signature for your def, they are +required to follow normal Python conventions (i.e., all +arguments are required except keyword arguments with a default +value). This is in contrast to using context-level variables, +which evaluate to UNDEFINED if you reference a name that +does not exist.

      +
      +

      Calling Defs from Other Files?

      +

      Top level <%def>s are exported by your template’s +module, and can be called from the outside; including from other +templates, as well as normal Python code. Calling a <%def> +from another template is something like using an <%include> +– except you are calling a specific function within the +template, not the whole template.

      +

      The remote <%def> call is also a little bit like calling +functions from other modules in Python. There is an “import” +step to pull the names from another template into your own +template; then the function or functions are available.

      +

      To import another template, use the <%namespace> tag:

      +
      <%namespace name="mystuff" file="mystuff.html"/>
      +
      +
      +

      The above tag adds a local variable mystuff to the current +scope.

      +

      Then, just call the defs off of mystuff:

      +
      ${mystuff.somedef(x=5,y=7)}
      +
      +
      +

      The <%namespace> tag also supports some of the other +semantics of Python’s import statement, including pulling +names into the local variable space, or using * to represent +all names, using the import attribute:

      +
      <%namespace file="mystuff.html" import="foo, bar"/>
      +
      +
      +

      This is just a quick intro to the concept of a namespace, +which is a central Mako concept that has its own chapter in +these docs. For more detail and examples, see +Namespaces.

      +
      +
      +

      Calling Defs Programmatically?

      +

      You can call defs programmatically from any Template object +using the get_def() method, which returns a DefTemplate +object. This is a Template subclass which the parent +Template creates, and is usable like any other template:

      +
      from mako.template import Template
      +
      +template = Template("""
      +    <%def name="hi(name)">
      +        hi ${name}!
      +    </%def>
      +
      +    <%def name="bye(name)">
      +        bye ${name}!
      +    </%def>
      +""")
      +
      +print template.get_def("hi").render(name="ed")
      +print template.get_def("bye").render(name="ed")
      +
      +
      +
      +
      +

      Defs within Defs?

      +

      The def model follows regular Python rules for closures. +Declaring <%def> inside another <%def> declares it +within the parent’s enclosing scope:

      +
      <%def name="mydef()">
      +    <%def name="subdef()">
      +        a sub def
      +    </%def>
      +
      +    i'm the def, and the subcomponent is ${subdef()}
      +</%def>
      +
      +
      +

      Just like Python, names that exist outside the inner <%def> +exist inside it as well:

      +
      <%
      +    x = 12
      +%>
      +<%def name="outer()">
      +    <%
      +        y = 15
      +    %>
      +    <%def name="inner()">
      +        inner, x is ${x}, y is ${y}
      +    </%def>
      +
      +    outer, x is ${x}, y is ${y}
      +</%def>
      +
      +
      +

      Assigning to a name inside of a def declares that name as local +to the scope of that def (again, like Python itself). This means +the following code will raise an error:

      +
      <%
      +    x = 10
      +%>
      +<%def name="somedef()">
      +    ## error !
      +    somedef, x is ${x}
      +    <%
      +        x = 27
      +    %>
      +</%def>
      +
      +
      +

      ...because the assignment to x declares x as local to the +scope of somedef, rendering the “outer” version unreachable +in the expression that tries to render it.

      +
      +
      +

      Calling a Def with Embedded Content and/or Other Defs?

      +

      A flip-side to def within def is a def call with content. This +is where you call a def, and at the same time declare a block of +content (or multiple blocks) that can be used by the def being +called. The main point of such a call is to create custom, +nestable tags, just like any other template language’s +custom-tag creation system – where the external tag controls the +execution of the nested tags and can communicate state to them. +Only with Mako, you don’t have to use any external Python +modules, you can define arbitrarily nestable tags right in your +templates.

      +

      To achieve this, the target def is invoked using the form +<%namepacename:defname> instead of the normal ${} +syntax. This syntax, introduced in Mako 0.2.3, is functionally +equivalent to another tag known as %call, which takes the form +<%call expr='namespacename.defname(args)'>. While %call +is available in all versions of Mako, the newer style is +probably more familiar looking. The namespace portion of the +call is the name of the namespace in which the def is +defined – in the most simple cases, this can be local or +self to reference the current template’s namespace (the +difference between local and self is one of inheritance +– see Built-in Namespaces for details).

      +

      When the target def is invoked, a variable caller is placed +in its context which contains another namespace containing the +body and other defs defined by the caller. The body itself is +referenced by the method body(). Below, we build a %def +that operates upon caller.body() to invoke the body of the +custom tag:

      +
      <%def name="buildtable()">
      +    <table>
      +        <tr><td>
      +            ${caller.body()}
      +        </td></tr>
      +    </table>
      +</%def>
      +
      +<%self:buildtable>
      +    I am the table body.
      +</%self:buildtable>
      +
      +
      +

      This produces the output (whitespace formatted):

      +
      <table>
      +    <tr><td>
      +        I am the table body.
      +    </td></tr>
      +</table>
      +
      +
      +

      Using the older %call syntax looks like:

      +
      <%def name="buildtable()">
      +    <table>
      +        <tr><td>
      +            ${caller.body()}
      +        </td></tr>
      +    </table>
      +</%def>
      +
      +<%call expr="buildtable()">
      +    I am the table body.
      +</%call>
      +
      +
      +

      The body() can be executed multiple times or not at all. +This means you can use def-call-with-content to build iterators, +conditionals, etc:

      +
      <%def name="lister(count)">
      +    % for x in range(count):
      +        ${caller.body()}
      +    % endfor
      +</%def>
      +
      +<%self:lister count="${3}">
      +    hi
      +</%self:lister>
      +
      +
      +

      Produces:

      +
      hi
      +hi
      +hi
      +
      +
      +

      Notice above we pass 3 as a Python expression, so that it +remains as an integer.

      +

      A custom “conditional” tag:

      +
      <%def name="conditional(expression)">
      +    % if expression:
      +        ${caller.body()}
      +    % endif
      +</%def>
      +
      +<%self:conditional expression="${4==4}">
      +    i'm the result
      +</%self:conditional>
      +
      +
      +

      Produces:

      +
      i'm the result
      +
      +
      +

      But that’s not all. The body() function also can handle +arguments, which will augment the local namespace of the body +callable. The caller must define the arguments which it expects +to receive from its target def using the args attribute, +which is a comma-separated list of argument names. Below, our +<%def> calls the body() of its caller, passing in an +element of data from its argument:

      +
      <%def name="layoutdata(somedata)">
      +    <table>
      +    % for item in somedata:
      +        <tr>
      +        % for col in item:
      +            <td>${caller.body(col=col)}</td>
      +        % endfor
      +        </tr>
      +    % endfor
      +    </table>
      +</%def>
      +
      +<%self:layoutdata somedata="${[[1,2,3],[4,5,6],[7,8,9]]}" args="col">\
      +Body data: ${col}\
      +</%self:layoutdata>
      +
      +
      +

      Produces:

      +
      <table>
      +    <tr>
      +        <td>Body data: 1</td>
      +        <td>Body data: 2</td>
      +        <td>Body data: 3</td>
      +    </tr>
      +    <tr>
      +        <td>Body data: 4</td>
      +        <td>Body data: 5</td>
      +        <td>Body data: 6</td>
      +    </tr>
      +    <tr>
      +        <td>Body data: 7</td>
      +        <td>Body data: 8</td>
      +        <td>Body data: 9</td>
      +    </tr>
      +</table>
      +
      +
      +

      You don’t have to stick to calling just the body() function. +The caller can define any number of callables, allowing the +<%call> tag to produce whole layouts:

      +
      <%def name="layout()">
      +    ## a layout def
      +    <div class="mainlayout">
      +        <div class="header">
      +            ${caller.header()}
      +        </div>
      +
      +        <div class="sidebar">
      +            ${caller.sidebar()}
      +        </div>
      +
      +        <div class="content">
      +            ${caller.body()}
      +        </div>
      +    </div>
      +</%def>
      +
      +## calls the layout def
      +<%self:layout>
      +    <%def name="header()">
      +        I am the header
      +    </%def>
      +    <%def name="sidebar()">
      +        <ul>
      +            <li>sidebar 1</li>
      +            <li>sidebar 2</li>
      +        </ul>
      +    </%def>
      +
      +        this is the body
      +</%self:layout>
      +
      +
      +

      The above layout would produce:

      +
      <div class="mainlayout">
      +    <div class="header">
      +    I am the header
      +    </div>
      +
      +    <div class="sidebar">
      +    <ul>
      +        <li>sidebar 1</li>
      +        <li>sidebar 2</li>
      +    </ul>
      +    </div>
      +
      +    <div class="content">
      +    this is the body
      +    </div>
      +</div>
      +
      +
      +

      The number of things you can do with <%call> and/or the +<%namespacename:defname> calling syntax is enormous. You can +create form widget libraries, such as an enclosing <FORM> +tag and nested HTML input elements, or portable wrapping schemes +using <div> or other elements. You can create tags that +interpret rows of data, such as from a database, providing the +individual columns of each row to a body() callable which +lays out the row any way it wants. Basically anything you’d do +with a “custom tag” or tag library in some other system, Mako +provides via <%def> tags and plain Python callables which are +invoked via <%namespacename:defname> or <%call>.

      +
      +
      +
      +

      Using Blocks?

      +

      The <%block> tag introduces some new twists on the +<%def> tag which make it more closely tailored towards layout.

      +

      +New in version 0.4.1.

      +

      An example of a block:

      +
      <html>
      +    <body>
      +        <%block>
      +            this is a block.
      +        </%block>
      +    </body>
      +</html>
      +
      +
      +

      In the above example, we define a simple block. The block renders its content in the place +that it’s defined. Since the block is called for us, it doesn’t need a name and the above +is referred to as an anonymous block. So the output of the above template will be:

      +
      <html>
      +    <body>
      +            this is a block.
      +    </body>
      +</html>
      +
      +
      +

      So in fact the above block has absolutely no effect. Its usefulness comes when we start +using modifiers. Such as, we can apply a filter to our block:

      +
      <html>
      +    <body>
      +        <%block filter="h">
      +            <html>this is some escaped html.</html>
      +        </%block>
      +    </body>
      +</html>
      +
      +
      +

      or perhaps a caching directive:

      +
      <html>
      +    <body>
      +        <%block cached="True" cache_timeout="60">
      +            This content will be cached for 60 seconds.
      +        </%block>
      +    </body>
      +</html>
      +
      +
      +

      Blocks also work in iterations, conditionals, just like defs:

      +
      % if some_condition:
      +    <%block>condition is met</%block>
      +% endif
      +
      +
      +

      While the block renders at the point it is defined in the template, +the underlying function is present in the generated Python code only +once, so there’s no issue with placing a block inside of a loop or +similar. Anonymous blocks are defined as closures in the local +rendering body, so have access to local variable scope:

      +
      % for i in range(1, 4):
      +    <%block>i is ${i}</%block>
      +% endfor
      +
      +
      +
      +

      Using Named Blocks?

      +

      Possibly the more important area where blocks are useful is when we +do actually give them names. Named blocks are tailored to behave +somewhat closely to Jinja2’s block tag, in that they define an area +of a layout which can be overridden by an inheriting template. In +sharp contrast to the <%def> tag, the name given to a block is +global for the entire template regardless of how deeply it’s nested:

      +
      <html>
      +<%block name="header">
      +    <head>
      +        <title>
      +            <%block name="title">Title</%block>
      +        </title>
      +    </head>
      +</%block>
      +<body>
      +    ${next.body()}
      +</body>
      +</html>
      +
      +
      +

      The above example has two named blocks “header” and “title”, both of which can be referred to +by an inheriting template. A detailed walkthrough of this usage can be found at Inheritance.

      +

      Note above that named blocks don’t have any argument declaration the way defs do. They still implement themselves +as Python functions, however, so they can be invoked additional times beyond their initial definition:

      +
      <div name="page">
      +    <%block name="pagecontrol">
      +        <a href="">previous page</a> |
      +        <a href="">next page</a>
      +    </%block>
      +
      +    <table>
      +        ## some content
      +    </table>
      +
      +    ${pagecontrol()}
      +</div>
      +
      +
      +

      The content referenced by pagecontrol above will be rendered both above and below the <table> tags.

      +

      To keep things sane, named blocks have restrictions that defs do not:

      +
        +
      • The <%block> declaration cannot have any argument signature.
      • +
      • The name of a <%block> can only be defined once in a template – an error is raised if two blocks of the same +name occur anywhere in a single template, regardless of nesting. A similar error is raised if a top level def +shares the same name as that of a block.
      • +
      • A named <%block> cannot be defined within a <%def>, or inside the body of a “call”, i.e. +<%call> or <%namespacename:defname> tag. Anonymous blocks can, however.
      • +
      +
      +
      +

      Using Page Arguments in Named Blocks?

      +

      A named block is very much like a top level def. It has a similar +restriction to these types of defs in that arguments passed to the +template via the <%page> tag aren’t automatically available. +Using arguments with the <%page> tag is described in the section +The body() Method, and refers to scenarios such as when the +body() method of a template is called from an inherited template passing +arguments, or the template is invoked from an <%include> tag +with arguments. To allow a named block to share the same arguments +passed to the page, the args attribute can be used:

      +
      <%page args="post"/>
      +
      +<a name="${post.title}" />
      +
      +<span class="post_prose">
      +    <%block name="post_prose" args="post">
      +        ${post.content}
      +    </%block>
      +</span>
      +
      +
      +

      Where above, if the template is called via a directive like +<%include file="post.mako" args="post=post" />, the post +variable is available both in the main body as well as the +post_prose block.

      +

      Similarly, the **pageargs variable is present, in named blocks only, +for those arguments not explicit in the <%page> tag:

      +
      <%block name="post_prose">
      +    ${pageargs['post'].content}
      +</%block>
      +
      +
      +

      The args attribute is only allowed with named blocks. With +anonymous blocks, the Python function is always rendered in the same +scope as the call itself, so anything available directly outside the +anonymous block is available inside as well.

      +
      +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/filtering.html b/lib/mako-0.7.2/doc/filtering.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/filtering.html @@ -0,0 +1,476 @@ + + + + + + + Filtering and Buffering + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Filtering and Buffering + + +

      + + Filtering and Buffering + +

      +
      + +
      + +
      + + + +
      + +
      +

      Filtering and Buffering?

      +
      +

      Expression Filtering?

      +

      As described in the chapter Syntax, the “|” operator can be +applied to a “${}” expression to apply escape filters to the +output:

      +
      ${"this is some text" | u}
      +
      +
      +

      The above expression applies URL escaping to the expression, and +produces this+is+some+text.

      +

      The built-in escape flags are:

      +
        +
      • u : URL escaping, provided by +urllib.quote_plus(string.encode('utf-8'))

        +
      • +
      • h : HTML escaping, provided by +markupsafe.escape(string)

        +

        +New in version 0.3.4: Prior versions use cgi.escape(string, True).

        +
      • +
      • x : XML escaping

        +
      • +
      • trim : whitespace trimming, provided by string.strip()

        +
      • +
      • entity : produces HTML entity references for applicable +strings, derived from htmlentitydefs

        +
      • +
      • unicode (str on Python 3): produces a Python unicode +string (this function is applied by default)

        +
      • +
      • decode.<some encoding>: decode input into a Python +unicode with the specified encoding

        +
      • +
      • n : disable all default filtering; only filters specified +in the local expression tag will be applied.

        +
      • +
      +

      To apply more than one filter, separate them by a comma:

      +
      ${" <tag>some value</tag> " | h,trim}
      +
      +
      +

      The above produces &lt;tag&gt;some value&lt;/tag&gt;, with +no leading or trailing whitespace. The HTML escaping function is +applied first, the “trim” function second.

      +

      Naturally, you can make your own filters too. A filter is just a +Python function that accepts a single string argument, and +returns the filtered result. The expressions after the | +operator draw upon the local namespace of the template in which +they appear, meaning you can define escaping functions locally:

      +
      <%!
      +    def myescape(text):
      +        return "<TAG>" + text + "</TAG>"
      +%>
      +
      +Here's some tagged text: ${"text" | myescape}
      +
      +
      +

      Or from any Python module:

      +
      <%!
      +    import myfilters
      +%>
      +
      +Here's some tagged text: ${"text" | myfilters.tagfilter}
      +
      +
      +

      A page can apply a default set of filters to all expression tags +using the expression_filter argument to the %page tag:

      +
      <%page expression_filter="h"/>
      +
      +Escaped text:  ${"<html>some html</html>"}
      +
      +
      +

      Result:

      +
      Escaped text: &lt;html&gt;some html&lt;/html&gt;
      +
      +
      +
      +

      The default_filters Argument?

      +

      In addition to the expression_filter argument, the +default_filters argument to both Template and +TemplateLookup can specify filtering for all expression tags +at the programmatic level. This array-based argument, when given +its default argument of None, will be internally set to +["unicode"] (or ["str"] on Python 3), except when +disable_unicode=True is set in which case it defaults to +["str"]:

      +
      t = TemplateLookup(directories=['/tmp'], default_filters=['unicode'])
      +
      +
      +

      To replace the usual unicode/str function with a +specific encoding, the decode filter can be substituted:

      +
      t = TemplateLookup(directories=['/tmp'], default_filters=['decode.utf8'])
      +
      +
      +

      To disable default_filters entirely, set it to an empty +list:

      +
      t = TemplateLookup(directories=['/tmp'], default_filters=[])
      +
      +
      +

      Any string name can be added to default_filters where it +will be added to all expressions as a filter. The filters are +applied from left to right, meaning the leftmost filter is +applied first.

      +
      t = Template(templatetext, default_filters=['unicode', 'myfilter'])
      +
      +
      +

      To ease the usage of default_filters with custom filters, +you can also add imports (or other code) to all templates using +the imports argument:

      +
      t = TemplateLookup(directories=['/tmp'],
      +                   default_filters=['unicode', 'myfilter'],
      +                   imports=['from mypackage import myfilter'])
      +
      +
      +

      The above will generate templates something like this:

      +
      # ....
      +from mypackage import myfilter
      +
      +def render_body(context):
      +    context.write(myfilter(unicode("some text")))
      +
      +
      +
      +
      +

      Turning off Filtering with the n Filter?

      +

      In all cases the special n filter, used locally within an +expression, will disable all filters declared in the +<%page> tag as well as in default_filters. Such as:

      +
      ${'myexpression' | n}
      +
      +
      +

      will render myexpression with no filtering of any kind, and:

      +
      ${'myexpression' | n,trim}
      +
      +
      +

      will render myexpression using the trim filter only.

      +
      +
      +
      +

      Filtering Defs and Blocks?

      +

      The %def and %block tags have an argument called filter which will apply the +given list of filter functions to the output of the %def:

      +
      <%def name="foo()" filter="h, trim">
      +    <b>this is bold</b>
      +</%def>
      +
      +
      +

      When the filter attribute is applied to a def as above, the def +is automatically buffered as well. This is described next.

      +
      +
      +

      Buffering?

      +

      One of Mako’s central design goals is speed. To this end, all of +the textual content within a template and its various callables +is by default piped directly to the single buffer that is stored +within the Context object. While this normally is easy to +miss, it has certain side effects. The main one is that when you +call a def using the normal expression syntax, i.e. +${somedef()}, it may appear that the return value of the +function is the content it produced, which is then delivered to +your template just like any other expression substitution, +except that normally, this is not the case; the return value of +${somedef()} is simply the empty string ''. By the time +you receive this empty string, the output of somedef() has +been sent to the underlying buffer.

      +

      You may not want this effect, if for example you are doing +something like this:

      +
      ${" results " + somedef() + " more results "}
      +
      +
      +

      If the somedef() function produced the content “somedef's +results”, the above template would produce this output:

      +
      somedef's results results more results
      +
      +
      +

      This is because somedef() fully executes before the +expression returns the results of its concatenation; the +concatenation in turn receives just the empty string as its +middle expression.

      +

      Mako provides two ways to work around this. One is by applying +buffering to the %def itself:

      +
      <%def name="somedef()" buffered="True">
      +    somedef's results
      +</%def>
      +
      +
      +

      The above definition will generate code similar to this:

      +
      def somedef():
      +    context.push_buffer()
      +    try:
      +        context.write("somedef's results")
      +    finally:
      +        buf = context.pop_buffer()
      +    return buf.getvalue()
      +
      +
      +

      So that the content of somedef() is sent to a second buffer, +which is then popped off the stack and its value returned. The +speed hit inherent in buffering the output of a def is also +apparent.

      +

      Note that the filter argument on %def also causes the def to +be buffered. This is so that the final content of the %def can +be delivered to the escaping function in one batch, which +reduces method calls and also produces more deterministic +behavior for the filtering function itself, which can possibly +be useful for a filtering function that wishes to apply a +transformation to the text as a whole.

      +

      The other way to buffer the output of a def or any Mako callable +is by using the built-in capture function. This function +performs an operation similar to the above buffering operation +except it is specified by the caller.

      +
      ${" results " + capture(somedef) + " more results "}
      +
      +
      +

      Note that the first argument to the capture function is +the function itself, not the result of calling it. This is +because the capture function takes over the job of actually +calling the target function, after setting up a buffered +environment. To send arguments to the function, just send them +to capture instead:

      +
      ${capture(somedef, 17, 'hi', use_paging=True)}
      +
      +
      +

      The above call is equivalent to the unbuffered call:

      +
      ${somedef(17, 'hi', use_paging=True)}
      +
      +
      +
      +
      +

      Decorating?

      +

      +New in version 0.2.5.

      +

      Somewhat like a filter for a %def but more flexible, the decorator +argument to %def allows the creation of a function that will +work in a similar manner to a Python decorator. The function can +control whether or not the function executes. The original +intent of this function is to allow the creation of custom cache +logic, but there may be other uses as well.

      +

      decorator is intended to be used with a regular Python +function, such as one defined in a library module. Here we’ll +illustrate the python function defined in the template for +simplicities’ sake:

      +
      <%!
      +    def bar(fn):
      +        def decorate(context, *args, **kw):
      +            context.write("BAR")
      +            fn(*args, **kw)
      +            context.write("BAR")
      +            return ''
      +        return decorate
      +%>
      +
      +<%def name="foo()" decorator="bar">
      +    this is foo
      +</%def>
      +
      +${foo()}
      +
      +
      +

      The above template will return, with more whitespace than this, +"BAR this is foo BAR". The function is the render callable +itself (or possibly a wrapper around it), and by default will +write to the context. To capture its output, use the capture() +callable in the mako.runtime module (available in templates +as just runtime):

      +
      <%!
      +    def bar(fn):
      +        def decorate(context, *args, **kw):
      +            return "BAR" + runtime.capture(context, fn, *args, **kw) + "BAR"
      +        return decorate
      +%>
      +
      +<%def name="foo()" decorator="bar">
      +    this is foo
      +</%def>
      +
      +${foo()}
      +
      +
      +

      The decorator can be used with top-level defs as well as nested +defs, and blocks too. Note that when calling a top-level def from the +Template API, i.e. template.get_def('somedef').render(), +the decorator has to write the output to the context, i.e. +as in the first example. The return value gets discarded.

      +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/genindex.html b/lib/mako-0.7.2/doc/genindex.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/genindex.html @@ -0,0 +1,914 @@ + + + + + + + Index + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Index + + +

      + + Index + +

      +
      + +
      + +
      + + +
      + + + + +

      Index

      + + A + | B + | C + | D + | E + | F + | G + | H + | I + | K + | L + | M + | N + | P + | R + | S + | T + | U + | W + +
      + +

      A

      +
      +
      + + +
      + adjust_uri() (mako.lookup.TemplateCollection method) +
      + +
      +
      (mako.lookup.TemplateLookup method) +
      +
      + + + +
      + + +
      + attr (mako.runtime.Namespace attribute) +
      + + + + +
      +
      +

      B

      +
      +
      + + +
      + BeakerCacheImpl (class in mako.ext.beaker_cache) +
      + + + + +
      + +
      +
      +

      C

      +
      +
      + + +
      + Cache (class in mako.cache) +
      + + + + + +
      + cache (mako.runtime.Namespace attribute) +
      + + + + + +
      + CacheImpl (class in mako.cache) +
      + + + + + +
      + capture() (in module mako.runtime) +
      + + + + + +
      + code (mako.template.Template attribute) +
      + + + + +
      + + +
      + Context (class in mako.runtime) +
      + + + + + +
      + context (mako.runtime.Namespace attribute) +
      + + + + + +
      + cycle() (mako.runtime.LoopContext method) +
      + + + + +
      +
      +

      D

      +
      +
      + + +
      + DefTemplate (class in mako.template) +
      + + + + +
      + +
      +
      +

      E

      +
      +
      + + +
      + error (RichTraceback attribute) +
      + + + + +
      + +
      +
      +

      F

      +
      +
      + + +
      + filename (mako.runtime.ModuleNamespace attribute) +
      + +
      +
      (mako.runtime.Namespace attribute) +
      +
      (mako.runtime.TemplateNamespace attribute) +
      +
      + + + +
      + + +
      + filename_to_uri() (mako.lookup.TemplateCollection method) +
      + +
      +
      (mako.lookup.TemplateLookup method) +
      +
      + + + +
      +
      +

      G

      +
      +
      + + +
      + get() (mako.cache.Cache method) +
      + +
      +
      (mako.cache.CacheImpl method) +
      +
      (mako.runtime.Context method) +
      +
      + + + + +
      + get_cached() (mako.runtime.Namespace method) +
      + + + + + +
      + get_def() (mako.template.Template method) +
      + + + + + +
      + get_namespace() (mako.runtime.Namespace method) +
      + + + + +
      + + +
      + get_or_create() (mako.cache.Cache method) +
      + +
      +
      (mako.cache.CacheImpl method) +
      +
      + + + + +
      + get_template() (mako.lookup.TemplateCollection method) +
      + +
      +
      (mako.lookup.TemplateLookup method) +
      +
      (mako.runtime.Namespace method) +
      +
      + + + +
      +
      +

      H

      +
      +
      + + +
      + has_template() (mako.lookup.TemplateCollection method) +
      + + + + + +
      + html_error_template() (in module mako.exceptions) +
      + + + + +
      + +
      +
      +

      I

      +
      +
      + + +
      + id (mako.cache.Cache attribute) +
      + + + + + +
      + impl (mako.cache.Cache attribute) +
      + + + + + +
      + include_file() (mako.runtime.Namespace method) +
      + + + + + +
      + invalidate() (mako.cache.Cache method) +
      + +
      +
      (mako.cache.CacheImpl method) +
      +
      + + + +
      + + +
      + invalidate_body() (mako.cache.Cache method) +
      + + + + + +
      + invalidate_closure() (mako.cache.Cache method) +
      + + + + + +
      + invalidate_def() (mako.cache.Cache method) +
      + + + + +
      +
      +

      K

      +
      +
      + + +
      + keys() (mako.runtime.Context method) +
      + + + + + +
      + kwargs (mako.runtime.Context attribute) +
      + + + + +
      + +
      +
      +

      L

      +
      +
      + + +
      + lineno (RichTraceback attribute) +
      + + + + + +
      + locals_() (mako.runtime.Context method) +
      + + + + + +
      + lookup (mako.runtime.Context attribute) +
      + + + + +
      + + +
      + LoopContext (class in mako.runtime) +
      + + + + +
      +
      +

      M

      +
      +
      + + +
      + message (RichTraceback attribute) +
      + + + + + +
      + module (mako.runtime.Namespace attribute) +
      + +
      +
      (mako.runtime.TemplateNamespace attribute) +
      +
      + + + +
      + + +
      + ModuleNamespace (class in mako.runtime) +
      + + + + +
      +
      +

      N

      +
      +
      + + +
      + Namespace (class in mako.runtime) +
      + + + + +
      + +
      +
      +

      P

      +
      +
      + + +
      + pass_context (mako.cache.CacheImpl attribute) +
      + + + + + +
      + pop_caller() (mako.runtime.Context method) +
      + + + + + +
      + push_caller() (mako.runtime.Context method) +
      + + + + + +
      + put() (mako.cache.Cache method) +
      + + + + +
      + + +
      + put_string() (mako.lookup.TemplateLookup method) +
      + + + + + +
      + put_template() (mako.lookup.TemplateLookup method) +
      + + + + +
      +
      +

      R

      +
      +
      + + +
      + records (RichTraceback attribute) +
      + + + + + +
      + register_plugin() (in module mako.cache) +
      + + + + + +
      + render() (mako.template.Template method) +
      + + + + + +
      + render_context() (mako.template.Template method) +
      + + + + + +
      + render_unicode() (mako.template.Template method) +
      + + + + +
      + + +
      + reverse_records (RichTraceback attribute) +
      + + + + + +
      + reverse_traceback (RichTraceback attribute) +
      + + + + + +
      + RichTraceback (class in mako.exceptions) +
      + + + + +
      +
      +

      S

      +
      +
      + + +
      + set() (mako.cache.Cache method) +
      + +
      +
      (mako.cache.CacheImpl method) +
      +
      + + + + +
      + source (mako.template.Template attribute) +
      + +
      +
      (RichTraceback attribute) +
      +
      + + + +
      + + +
      + starttime (mako.cache.Cache attribute) +
      + + + + + +
      + supports_caller() (in module mako.runtime) +
      + + + + +
      +
      +

      T

      +
      +
      + + +
      + Template (class in mako.template) +
      + + + + + +
      + template (mako.runtime.Namespace attribute) +
      + + + + + +
      + TemplateCollection (class in mako.lookup) +
      + + + + + +
      + TemplateLookup (class in mako.lookup) +
      + + + + +
      + + +
      + TemplateNamespace (class in mako.runtime) +
      + + + + + +
      + text_error_template() (in module mako.exceptions) +
      + + + + +
      +
      +

      U

      +
      +
      + + +
      + Undefined (class in mako.runtime) +
      + + + + + +
      + uri (mako.runtime.Namespace attribute) +
      + +
      +
      (mako.runtime.TemplateNamespace attribute) +
      +
      + + + +
      + +
      +
      +

      W

      +
      +
      + + +
      + write() (mako.runtime.Context method) +
      + + + + + +
      + writer() (mako.runtime.Context method) +
      + + + + +
      + +
      +
      + + + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/index.html b/lib/mako-0.7.2/doc/index.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/index.html @@ -0,0 +1,228 @@ + + + + + + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + +

      + + Table of Contents + +

      +
      + +
      + + + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/inheritance.html b/lib/mako-0.7.2/doc/inheritance.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/inheritance.html @@ -0,0 +1,671 @@ + + + + + + + Inheritance + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Inheritance + + +

      + + Inheritance + +

      +
      + +
      + +
      + + + +
      + +
      +

      Inheritance?

      +
      +

      Note

      +

      Most of the inheritance examples here take advantage of a feature that’s +new in Mako as of version 0.4.1 called the “block”. This tag is very similar to +the “def” tag but is more streamlined for usage with inheritance. Note that +all of the examples here which use blocks can also use defs instead. Contrasting +usages will be illustrated.

      +
      +

      Using template inheritance, two or more templates can organize +themselves into an inheritance chain, where content and +functions from all involved templates can be intermixed. The +general paradigm of template inheritance is this: if a template +A inherits from template B, then template A agrees +to send the executional control to template B at runtime +(A is called the inheriting template). Template B, +the inherited template, then makes decisions as to what +resources from A shall be executed.

      +

      In practice, it looks like this. Here’s a hypothetical inheriting +template, index.html:

      +
      ## index.html
      +<%inherit file="base.html"/>
      +
      +<%block name="header">
      +    this is some header content
      +</%block>
      +
      +this is the body content.
      +
      +
      +

      And base.html, the inherited template:

      +
      ## base.html
      +<html>
      +    <body>
      +        <div class="header">
      +            <%block name="header"/>
      +        </div>
      +
      +        ${self.body()}
      +
      +        <div class="footer">
      +            <%block name="footer">
      +                this is the footer
      +            </%block>
      +        </div>
      +    </body>
      +</html>
      +
      +
      +

      Here is a breakdown of the execution:

      +
        +
      1. When index.html is rendered, control immediately passes to +base.html.

        +
      2. +
      3. base.html then renders the top part of an HTML document, +then invokes the <%block name="header"> block. It invokes the +underlying header() function off of a built-in namespace +called self (this namespace was first introduced in the +Namespaces chapter in self). Since +index.html is the topmost template and also defines a block +called header, it’s this header block that ultimately gets +executed – instead of the one that’s present in base.html.

        +
      4. +
      5. Control comes back to base.html. Some more HTML is +rendered.

        +
      6. +
      7. base.html executes self.body(). The body() +function on all template-based namespaces refers to the main +body of the template, therefore the main body of +index.html is rendered.

        +
      8. +
      9. When <%block name="header"> is encountered in index.html +during the self.body() call, a conditional is checked – does the +current inherited template, i.e. base.html, also define this block? If yes, +the <%block> is not executed here – the inheritance +mechanism knows that the parent template is responsible for rendering +this block (and in fact it already has). In other words a block +only renders in its basemost scope.

        +
      10. +
      11. Control comes back to base.html. More HTML is rendered, +then the <%block name="footer"> expression is invoked.

        +
      12. +
      13. The footer block is only defined in base.html, so being +the topmost definition of footer, it’s the one that +executes. If index.html also specified footer, then +its version would override that of the base.

        +
      14. +
      15. base.html finishes up rendering its HTML and the template +is complete, producing:

        +
        <html>
        +    <body>
        +        <div class="header">
        +            this is some header content
        +        </div>
        +
        +        this is the body content.
        +
        +        <div class="footer">
        +            this is the footer
        +        </div>
        +    </body>
        +</html>
        +
        +
        +
      16. +
      +

      ...and that is template inheritance in a nutshell. The main idea +is that the methods that you call upon self always +correspond to the topmost definition of that method. Very much +the way self works in a Python class, even though Mako is +not actually using Python class inheritance to implement this +functionality. (Mako doesn’t take the “inheritance” metaphor too +seriously; while useful to setup some commonly recognized +semantics, a textual template is not very much like an +object-oriented class construct in practice).

      +
      +

      Nesting Blocks?

      +

      The named blocks defined in an inherited template can also be nested within +other blocks. The name given to each block is globally accessible via any inheriting +template. We can add a new block title to our header block:

      +
      ## base.html
      +<html>
      +    <body>
      +        <div class="header">
      +            <%block name="header">
      +                <h2>
      +                    <%block name="title"/>
      +                </h2>
      +            </%block>
      +        </div>
      +
      +        ${self.body()}
      +
      +        <div class="footer">
      +            <%block name="footer">
      +                this is the footer
      +            </%block>
      +        </div>
      +    </body>
      +</html>
      +
      +
      +

      The inheriting template can name either or both of header and title, separately +or nested themselves:

      +
      ## index.html
      +<%inherit file="base.html"/>
      +
      +<%block name="header">
      +    this is some header content
      +    ${parent.header()}
      +</%block>
      +
      +<%block name="title">
      +    this is the title
      +</%block>
      +
      +this is the body content.
      +
      +
      +

      Note when we overrode header, we added an extra call ${parent.header()} in order to invoke +the parent’s header block in addition to our own. That’s described in more detail below, +in Using the parent Namespace to Augment Defs.

      +
      +
      +

      Rendering a Named Block Multiple Times?

      +

      Recall from the section Using Blocks that a named block is just like a <%def>, +with some different usage rules. We can call one of our named sections distinctly, for example +a section that is used more than once, such as the title of a page:

      +
      <html>
      +    <head>
      +        <title>${self.title()}</title>
      +    </head>
      +    <body>
      +    <%block name="header">
      +        <h2><%block name="title"/></h2>
      +    </%block>
      +    ${self.body()}
      +    </body>
      +</html>
      +
      +
      +

      Where above an inheriting template can define <%block name="title"> just once, and it will be +used in the base template both in the <title> section as well as the <h2>.

      +
      +
      +

      But what about Defs??

      +

      The previous example used the <%block> tag to produce areas of content +to be overridden. Before Mako 0.4.1, there wasn’t any such tag – instead +there was only the <%def> tag. As it turns out, named blocks and defs are +largely interchangeable. The def simply doesn’t call itself automatically, +and has more open-ended naming and scoping rules that are more flexible and similar +to Python itself, but less suited towards layout. The first example from +this chapter using defs would look like:

      +
      ## index.html
      +<%inherit file="base.html"/>
      +
      +<%def name="header()">
      +    this is some header content
      +</%def>
      +
      +this is the body content.
      +
      +
      +

      And base.html, the inherited template:

      +
      ## base.html
      +<html>
      +    <body>
      +        <div class="header">
      +            ${self.header()}
      +        </div>
      +
      +        ${self.body()}
      +
      +        <div class="footer">
      +            ${self.footer()}
      +        </div>
      +    </body>
      +</html>
      +
      +<%def name="header()"/>
      +<%def name="footer()">
      +    this is the footer
      +</%def>
      +
      +
      +

      Above, we illustrate that defs differ from blocks in that their definition +and invocation are defined in two separate places, instead of at once. You can almost do exactly what a +block does if you put the two together:

      +
      <div class="header">
      +    <%def name="header()"></%def>${self.header()}
      +</div>
      +
      +
      +

      The <%block> is obviously more streamlined than the <%def> for this kind +of usage. In addition, +the above “inline” approach with <%def> does not work with nesting:

      +
      <head>
      +    <%def name="header()">
      +        <title>
      +        ## this won't work !
      +        <%def name="title()">default title</%def>${self.title()}
      +        </title>
      +    </%def>${self.header()}
      +</head>
      +
      +
      +

      Where above, the title() def, because it’s a def within a def, is not part of the +template’s exported namespace and will not be part of self. If the inherited template +did define its own title def at the top level, it would be called, but the “default title” +above is not present at all on self no matter what. For this to work as expected +you’d instead need to say:

      +
      <head>
      +    <%def name="header()">
      +        <title>
      +        ${self.title()}
      +        </title>
      +    </%def>${self.header()}
      +
      +    <%def name="title()"/>
      +</head>
      +
      +
      +

      That is, title is defined outside of any other defs so that it is in the self namespace. +It works, but the definition needs to be potentially far away from the point of render.

      +

      A named block is always placed in the self namespace, regardless of nesting, +so this restriction is lifted:

      +
      ## base.html
      +<head>
      +    <%block name="header">
      +        <title>
      +        <%block name="title"/>
      +        </title>
      +    </%block>
      +</head>
      +
      +
      +

      The above template defines title inside of header, and an inheriting template can define +one or both in any configuration, nested inside each other or not, in order for them to be used:

      +
      ## index.html
      +<%inherit file="base.html"/>
      +<%block name="title">
      +    the title
      +</%block>
      +<%block name="header">
      +    the header
      +</%block>
      +
      +
      +

      So while the <%block> tag lifts the restriction of nested blocks not being available externally, +in order to achieve this it adds the restriction that all block names in a single template need +to be globally unique within the template, and additionally that a <%block> can’t be defined +inside of a <%def>. It’s a more restricted tag suited towards a more specific use case than <%def>.

      +
      +
      +

      Using the next Namespace to Produce Content Wrapping?

      +

      Sometimes you have an inheritance chain that spans more than two +templates. Or maybe you don’t, but you’d like to build your +system such that extra inherited templates can be inserted in +the middle of a chain where they would be smoothly integrated. +If each template wants to define its layout just within its main +body, you can’t just call self.body() to get at the +inheriting template’s body, since that is only the topmost body. +To get at the body of the next template, you call upon the +namespace next, which is the namespace of the template +immediately following the current template.

      +

      Lets change the line in base.html which calls upon +self.body() to instead call upon next.body():

      +
      ## base.html
      +<html>
      +    <body>
      +        <div class="header">
      +            <%block name="header"/>
      +        </div>
      +
      +        ${next.body()}
      +
      +        <div class="footer">
      +            <%block name="footer">
      +                this is the footer
      +            </%block>
      +        </div>
      +    </body>
      +</html>
      +
      +
      +

      Lets also add an intermediate template called layout.html, +which inherits from base.html:

      +
      ## layout.html
      +<%inherit file="base.html"/>
      +<ul>
      +    <%block name="toolbar">
      +        <li>selection 1</li>
      +        <li>selection 2</li>
      +        <li>selection 3</li>
      +    </%block>
      +</ul>
      +<div class="mainlayout">
      +    ${next.body()}
      +</div>
      +
      +
      +

      And finally change index.html to inherit from +layout.html instead:

      +
      ## index.html
      +<%inherit file="layout.html"/>
      +
      +## .. rest of template
      +
      +
      +

      In this setup, each call to next.body() will render the body +of the next template in the inheritance chain (which can be +written as base.html -> layout.html -> index.html). Control +is still first passed to the bottommost template base.html, +and self still references the topmost definition of any +particular def.

      +

      The output we get would be:

      +
      <html>
      +    <body>
      +        <div class="header">
      +            this is some header content
      +        </div>
      +
      +        <ul>
      +            <li>selection 1</li>
      +            <li>selection 2</li>
      +            <li>selection 3</li>
      +        </ul>
      +
      +        <div class="mainlayout">
      +        this is the body content.
      +        </div>
      +
      +        <div class="footer">
      +            this is the footer
      +        </div>
      +    </body>
      +</html>
      +
      +
      +

      So above, we have the <html>, <body> and +header/footer layout of base.html, we have the +<ul> and mainlayout section of layout.html, and the +main body of index.html as well as its overridden header +def. The layout.html template is inserted into the middle of +the chain without base.html having to change anything. +Without the next namespace, only the main body of +index.html could be used; there would be no way to call +layout.html‘s body content.

      +
      +
      +

      Using the parent Namespace to Augment Defs?

      +

      Lets now look at the other inheritance-specific namespace, the +opposite of next called parent. parent is the +namespace of the template immediately preceding the current +template. What’s useful about this namespace is that +defs or blocks can call upon their overridden versions. +This is not as hard as it sounds and +is very much like using the super keyword in Python. Lets +modify index.html to augment the list of selections provided +by the toolbar function in layout.html:

      +
      ## index.html
      +<%inherit file="layout.html"/>
      +
      +<%block name="header">
      +    this is some header content
      +</%block>
      +
      +<%block name="toolbar">
      +    ## call the parent's toolbar first
      +    ${parent.toolbar()}
      +    <li>selection 4</li>
      +    <li>selection 5</li>
      +</%block>
      +
      +this is the body content.
      +
      +
      +

      Above, we implemented a toolbar() function, which is meant +to override the definition of toolbar within the inherited +template layout.html. However, since we want the content +from that of layout.html as well, we call it via the +parent namespace whenever we want it’s content, in this case +before we add our own selections. So the output for the whole +thing is now:

      +
      <html>
      +    <body>
      +        <div class="header">
      +            this is some header content
      +        </div>
      +
      +        <ul>
      +            <li>selection 1</li>
      +            <li>selection 2</li>
      +            <li>selection 3</li>
      +            <li>selection 4</li>
      +            <li>selection 5</li>
      +        </ul>
      +
      +        <div class="mainlayout">
      +        this is the body content.
      +        </div>
      +
      +        <div class="footer">
      +            this is the footer
      +        </div>
      +    </body>
      +</html>
      +
      +
      +

      and you’re now a template inheritance ninja!

      +
      +
      +

      Inheritable Attributes?

      +

      The attr accessor of the Namespace object +allows access to module level variables declared in a template. By accessing +self.attr, you can access regular attributes from the +inheritance chain as declared in <%! %> sections. Such as:

      +
      <%!
      +    class_ = "grey"
      +%>
      +
      +<div class="${self.attr.class_}">
      +    ${self.body()}
      +</div>
      +
      +
      +

      If an inheriting template overrides class_ to be +"white", as in:

      +
      <%!
      +    class_ = "white"
      +%>
      +<%inherit file="parent.html"/>
      +
      +This is the body
      +
      +
      +

      you’ll get output like:

      +
      <div class="white">
      +    This is the body
      +</div>
      +
      +
      +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/namespaces.html b/lib/mako-0.7.2/doc/namespaces.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/namespaces.html @@ -0,0 +1,647 @@ + + + + + + + Namespaces + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Namespaces + + +

      + + Namespaces + +

      +
      + +
      + +
      + + + +
      + +
      +

      Namespaces?

      +

      Namespaces are used to organize groups of defs into +categories, and also to “import” defs from other files.

      +

      If the file components.html defines these two defs:

      +
      ## components.html
      +<%def name="comp1()">
      +    this is comp1
      +</%def>
      +
      +<%def name="comp2(x)">
      +    this is comp2, x is ${x}
      +</%def>
      +
      +
      +

      you can make another file, for example index.html, that +pulls those two defs into a namespace called comp:

      +
      ## index.html
      +<%namespace name="comp" file="components.html"/>
      +
      +Here's comp1:  ${comp.comp1()}
      +Here's comp2:  ${comp.comp2(x=5)}
      +
      +
      +

      The comp variable above is an instance of +Namespace, a proxy object which delivers +method calls to the underlying template callable using the +current context.

      +

      <%namespace> also provides an import attribute which can +be used to pull the names into the local namespace, removing the +need to call it via the “.” operator. When import is used, the +name attribute is optional.

      +
      <%namespace file="components.html" import="comp1, comp2"/>
      +
      +Heres comp1:  ${comp1()}
      +Heres comp2:  ${comp2(x=5)}
      +
      +
      +

      import also supports the “*” operator:

      +
      <%namespace file="components.html" import="*"/>
      +
      +Heres comp1:  ${comp1()}
      +Heres comp2:  ${comp2(x=5)}
      +
      +
      +

      The names imported by the import attribute take precedence +over any names that exist within the current context.

      +
      +

      Note

      +

      In current versions of Mako, usage of import='*' is +known to decrease performance of the template. This will be +fixed in a future release.

      +
      +

      The file argument allows expressions – if looking for +context variables, the context must be named explicitly:

      +
      <%namespace name="dyn" file="${context['namespace_name']}"/>
      +
      +
      +
      +

      Ways to Call Namespaces?

      +

      There are essentially four ways to call a function from a +namespace.

      +

      The “expression” format, as described previously. Namespaces are +just Python objects with functions on them, and can be used in +expressions like any other function:

      +
      ${mynamespace.somefunction('some arg1', 'some arg2', arg3='some arg3', arg4='some arg4')}
      +
      +
      +

      Synonymous with the “expression” format is the “custom tag” +format, when a “closed” tag is used. This format, introduced in +Mako 0.2.3, allows the usage of a “custom” Mako tag, with the +function arguments passed in using named attributes:

      +
      <%mynamespace:somefunction arg1="some arg1" arg2="some arg2" arg3="some arg3" arg4="some arg4"/>
      +
      +
      +

      When using tags, the values of the arguments are taken as +literal strings by default. To embed Python expressions as +arguments, use the embedded expression format:

      +
      <%mynamespace:somefunction arg1="${someobject.format()}" arg2="${somedef(5, 12)}"/>
      +
      +
      +

      The “custom tag” format is intended mainly for namespace +functions which recognize body content, which in Mako is known +as a “def with embedded content”:

      +
      <%mynamespace:somefunction arg1="some argument" args="x, y">
      +    Some record: ${x}, ${y}
      +</%mynamespace:somefunction>
      +
      +
      +

      The “classic” way to call defs with embedded content is the <%call> tag:

      +
      <%call expr="mynamespace.somefunction(arg1='some argument')" args="x, y">
      +    Some record: ${x}, ${y}
      +</%call>
      +
      +
      +

      For information on how to construct defs that embed content from +the caller, see Calling a Def with Embedded Content and/or Other Defs.

      +
      +
      +

      Namespaces from Regular Python Modules?

      +

      Namespaces can also import regular Python functions from +modules. These callables need to take at least one argument, +context, an instance of Context. A module file +some/module.py might contain the callable:

      +
      def my_tag(context):
      +    context.write("hello world")
      +    return ''
      +
      +
      +

      A template can use this module via:

      +
      <%namespace name="hw" module="some.module"/>
      +
      +${hw.my_tag()}
      +
      +
      +

      Note that the context argument is not needed in the call; +the Namespace tag creates a locally-scoped callable which +takes care of it. The return '' is so that the def does not +dump a None into the output stream – the return value of any +def is rendered after the def completes, in addition to whatever +was passed to Context.write() within its body.

      +

      If your def is to be called in an “embedded content” context, +that is as described in Calling a Def with Embedded Content and/or Other Defs, you should use +the supports_caller() decorator, which will ensure that Mako +will ensure the correct “caller” variable is available when your +def is called, supporting embedded content:

      +
      from mako.runtime import supports_caller
      +
      +@supports_caller
      +def my_tag(context):
      +    context.write("<div>")
      +    context['caller'].body()
      +    context.write("</div>")
      +    return ''
      +
      +
      +

      Capturing of output is available as well, using the +outside-of-templates version of the capture() function, +which accepts the “context” as its first argument:

      +
      from mako.runtime import supports_caller, capture
      +
      +@supports_caller
      +def my_tag(context):
      +    return "<div>%s</div>" % \
      +            capture(context, context['caller'].body, x="foo", y="bar")
      +
      +
      +
      +
      +

      Declaring Defs in Namespaces?

      +

      The <%namespace> tag supports the definition of <%def>s +directly inside the tag. These defs become part of the namespace +like any other function, and will override the definitions +pulled in from a remote template or module:

      +
      ## define a namespace
      +<%namespace name="stuff">
      +    <%def name="comp1()">
      +        comp1
      +    </%def>
      +</%namespace>
      +
      +## then call it
      +${stuff.comp1()}
      +
      +
      +
      +
      +

      The body() Method?

      +

      Every namespace that is generated from a template contains a +method called body(). This method corresponds to the main +body of the template, and plays its most important roles when +using inheritance relationships as well as +def-calls-with-content.

      +

      Since the body() method is available from a namespace just +like all the other defs defined in a template, what happens if +you send arguments to it? By default, the body() method +accepts no positional arguments, and for usefulness in +inheritance scenarios will by default dump all keyword arguments +into a dictionary called pageargs. But if you actually want +to get at the keyword arguments, Mako recommends you define your +own argument signature explicitly. You do this via using the +<%page> tag:

      +
      <%page args="x, y, someval=8, scope='foo', **kwargs"/>
      +
      +
      +

      A template which defines the above signature requires that the +variables x and y are defined, defines default values +for someval and scope, and sets up **kwargs to +receive all other keyword arguments. If **kwargs or similar +is not present, the argument **pageargs gets tacked on by +Mako. When the template is called as a top-level template (i.e. +via render()) or via the <%include> tag, the +values for these arguments will be pulled from the Context. +In all other cases, i.e. via calling the body() method, the +arguments are taken as ordinary arguments from the method call. +So above, the body might be called as:

      +
      ${self.body(5, y=10, someval=15, delta=7)}
      +
      +
      +

      The Context object also supplies a kwargs accessor, for +cases when you’d like to pass along whatever is in the context to +a body() callable:

      +
      ${next.body(**context.kwargs)}
      +
      +
      +

      The usefulness of calls like the above become more apparent when +one works with inheriting templates. For more information on +this, as well as the meanings of the names self and +next, see Inheritance.

      +
      +
      +

      Built-in Namespaces?

      +

      The namespace is so great that Mako gives your template one (or +two) for free. The names of these namespaces are local and +self. Other built-in namespaces include parent and +next, which are optional and are described in +Inheritance.

      +
      +

      local?

      +

      The local namespace is basically the namespace for the +currently executing template. This means that all of the top +level defs defined in your template, as well as your template’s +body() function, are also available off of the local +namespace.

      +

      The local namespace is also where properties like uri, +filename, and module and the get_namespace method +can be particularly useful.

      +
      +
      +

      self?

      +

      The self namespace, in the case of a template that does not +use inheritance, is synonymous with local. If inheritance is +used, then self references the topmost template in the +inheritance chain, where it is most useful for providing the +ultimate form of various “method” calls which may have been +overridden at various points in an inheritance chain. See +Inheritance.

      +
      +
      +
      +

      Inheritable Namespaces?

      +

      The <%namespace> tag includes an optional attribute +inheritable="True", which will cause the namespace to be +attached to the self namespace. Since self is globally +available throughout an inheritance chain (described in the next +section), all the templates in an inheritance chain can get at +the namespace imported in a super-template via self.

      +
      ## base.html
      +<%namespace name="foo" file="foo.html" inheritable="True"/>
      +
      +${next.body()}
      +
      +## somefile.html
      +<%inherit file="base.html"/>
      +
      +${self.foo.bar()}
      +
      +
      +

      This allows a super-template to load a whole bunch of namespaces +that its inheriting templates can get to, without them having to +explicitly load those namespaces themselves.

      +

      The import="*" part of the <%namespace> tag doesn’t yet +interact with the inheritable flag, so currently you have to +use the explicit namespace name off of self, followed by the +desired function name. But more on this in a future release.

      +
      +
      +

      API Reference?

      +
      +
      +class mako.runtime.Namespace(name, context, callables=None, inherits=None, populate_self=True, calling_uri=None)?
      +

      Bases: object

      +

      Provides access to collections of rendering methods, which +can be local, from other templates, or from imported modules.

      +

      To access a particular rendering method referenced by a +Namespace, use plain attribute access:

      +
      ${some_namespace.foo(x, y, z)}
      +
      +
      +

      Namespace also contains several built-in attributes +described here.

      +
      +
      +attr?
      +

      Access module level attributes by name.

      +

      This accessor allows templates to supply “scalar” +attributes which are particularly handy in inheritance +relationships. See the example in +Inheritance.

      +
      + +
      +
      +cache?
      +

      Return the Cache object referenced +by this Namespace object’s +Template.

      +
      + +
      +
      +context = None?
      +

      The Context object for this Namespace.

      +

      Namespaces are often created with copies of contexts that +contain slightly different data, particularly in inheritance +scenarios. Using the Context off of a Namespace one +can traverse an entire chain of templates that inherit from +one-another.

      +
      + +
      +
      +filename = None?
      +

      The path of the filesystem file used for this +Namespace‘s module or template.

      +

      If this is a pure module-based +Namespace, this evaluates to module.__file__. If a +template-based namespace, it evaluates to the original +template file location.

      +
      + +
      +
      +get_cached(key, **kwargs)?
      +

      Return a value from the Cache referenced by this +Namespace object’s Template.

      +

      The advantage to this method versus direct access to the +Cache is that the configuration parameters +declared in <%page> take effect here, thereby calling +up the same configured backend as that configured +by <%page>.

      +
      + +
      +
      +get_namespace(uri)?
      +

      Return a Namespace corresponding to the given uri.

      +

      If the given uri is a relative URI (i.e. it does not +contain a leading slash /), the uri is adjusted to +be relative to the uri of the namespace itself. This +method is therefore mostly useful off of the built-in +local namespace, described in local.

      +

      In +most cases, a template wouldn’t need this function, and +should instead use the <%namespace> tag to load +namespaces. However, since all <%namespace> tags are +evaluated before the body of a template ever runs, +this method can be used to locate namespaces using +expressions that were generated within the body code of +the template, or to conditionally use a particular +namespace.

      +
      + +
      +
      +get_template(uri)?
      +

      Return a Template from the given uri.

      +

      The uri resolution is relative to the uri of this Namespace +object’s Template.

      +
      + +
      +
      +include_file(uri, **kwargs)?
      +

      Include a file at the given uri.

      +
      + +
      +
      +module = None?
      +

      The Python module referenced by this Namespace.

      +

      If the namespace references a Template, then +this module is the equivalent of template.module, +i.e. the generated module for the template.

      +
      + +
      +
      +template = None?
      +

      The Template object referenced by this +Namespace, if any.

      +
      + +
      +
      +uri = None?
      +

      The URI for this Namespace‘s template.

      +

      I.e. whatever was sent to TemplateLookup.get_template().

      +

      This is the equivalent of Template.uri.

      +
      + +
      + +
      +
      +class mako.runtime.TemplateNamespace(name, context, template=None, templateuri=None, callables=None, inherits=None, populate_self=True, calling_uri=None)?
      +

      Bases: mako.runtime.Namespace

      +

      A Namespace specific to a Template instance.

      +
      +
      +filename?
      +

      The path of the filesystem file used for this +Namespace‘s module or template.

      +
      + +
      +
      +module?
      +

      The Python module referenced by this Namespace.

      +

      If the namespace references a Template, then +this module is the equivalent of template.module, +i.e. the generated module for the template.

      +
      + +
      +
      +uri?
      +

      The URI for this Namespace‘s template.

      +

      I.e. whatever was sent to TemplateLookup.get_template().

      +

      This is the equivalent of Template.uri.

      +
      + +
      + +
      +
      +class mako.runtime.ModuleNamespace(name, context, module, callables=None, inherits=None, populate_self=True, calling_uri=None)?
      +

      Bases: mako.runtime.Namespace

      +

      A Namespace specific to a Python module instance.

      +
      +
      +filename?
      +

      The path of the filesystem file used for this +Namespace‘s module or template.

      +
      + +
      + +
      +
      +mako.runtime.supports_caller(func)?
      +

      Apply a caller_stack compatibility decorator to a plain +Python function.

      +

      See the example in Namespaces from Regular Python Modules.

      +
      + +
      +
      +mako.runtime.capture(context, callable_, *args, **kwargs)?
      +

      Execute the given template def, capturing the output into +a buffer.

      +

      See the example in Namespaces from Regular Python Modules.

      +
      + +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/runtime.html b/lib/mako-0.7.2/doc/runtime.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/runtime.html @@ -0,0 +1,708 @@ + + + + + + + The Mako Runtime Environment + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + The Mako Runtime Environment + + +

      + + The Mako Runtime Environment + +

      +
      + +
      + +
      + + + +
      + +
      +

      The Mako Runtime Environment?

      +

      This section describes a little bit about the objects and +built-in functions that are available in templates.

      +
      +

      Context?

      +

      The Context is the central object that is created when +a template is first executed, and is responsible for handling +all communication with the outside world. Within the template +environment, it is available via the reserved name +context. The Context includes two +major components, one of which is the output buffer, which is a +file-like object such as Python’s StringIO or similar, and +the other a dictionary of variables that can be freely +referenced within a template; this dictionary is a combination +of the arguments sent to the render() function and +some built-in variables provided by Mako’s runtime environment.

      +
      +

      The Buffer?

      +

      The buffer is stored within the Context, and writing +to it is achieved by calling the write() method +– in a template this looks like context.write('some string'). +You usually don’t need to care about this, as all text within a template, as +well as all expressions provided by ${}, automatically send +everything to this method. The cases you might want to be aware +of its existence are if you are dealing with various +filtering/buffering scenarios, which are described in +Filtering and Buffering, or if you want to programmatically +send content to the output stream, such as within a <% %> +block.

      +
      <%
      +    context.write("some programmatic text")
      +%>
      +
      +
      +

      The actual buffer may or may not be the original buffer sent to +the Context object, as various filtering/caching +scenarios may “push” a new buffer onto the context’s underlying +buffer stack. For this reason, just stick with +context.write() and content will always go to the topmost +buffer.

      +
      +
      +

      Context Variables?

      +

      When your template is compiled into a Python module, the body +content is enclosed within a Python function called +render_body. Other top-level defs defined in the template are +defined within their own function bodies which are named after +the def’s name with the prefix render_ (i.e. render_mydef). +One of the first things that happens within these functions is +that all variable names that are referenced within the function +which are not defined in some other way (i.e. such as via +assignment, module level imports, etc.) are pulled from the +Context object’s dictionary of variables. This is how you’re +able to freely reference variable names in a template which +automatically correspond to what was passed into the current +Context.

      +
        +
      • What happens if I reference a variable name that is not in +the current context? - The value you get back is a special +value called UNDEFINED, or if the strict_undefined=True flag +is used a NameError is raised. UNDEFINED is just a simple global +variable with the class mako.runtime.Undefined. The +UNDEFINED object throws an error when you call str() on +it, which is what happens if you try to use it in an +expression.

        +
      • +
      • UNDEFINED makes it hard for me to find what name is missing - An alternative +is to specify the option strict_undefined=True +to the Template or TemplateLookup. This will cause +any non-present variables to raise an immediate NameError +which includes the name of the variable in its message +when render() is called – UNDEFINED is not used.

        +

        +New in version 0.3.6.

        +
      • +
      • Why not just return None? Using UNDEFINED, or +raising a NameError is more +explicit and allows differentiation between a value of None +that was explicitly passed to the Context and a value that +wasn’t present at all.

        +
      • +
      • Why raise an exception when you call str() on it ? Why not +just return a blank string? - Mako tries to stick to the +Python philosophy of “explicit is better than implicit”. In +this case, it’s decided that the template author should be made +to specifically handle a missing value rather than +experiencing what may be a silent failure. Since UNDEFINED +is a singleton object just like Python’s True or False, +you can use the is operator to check for it:

        +
        % if someval is UNDEFINED:
        +    someval is: no value
        +% else:
        +    someval is: ${someval}
        +% endif
        +
        +
        +
      • +
      +

      Another facet of the Context is that its dictionary of +variables is immutable. Whatever is set when +render() is called is what stays. Of course, since +its Python, you can hack around this and change values in the +context’s internal dictionary, but this will probably will not +work as well as you’d think. The reason for this is that Mako in +many cases creates copies of the Context object, which +get sent to various elements of the template and inheriting +templates used in an execution. So changing the value in your +local Context will not necessarily make that value +available in other parts of the template’s execution. Examples +of where Mako creates copies of the Context include +within top-level def calls from the main body of the template +(the context is used to propagate locally assigned variables +into the scope of defs; since in the template’s body they appear +as inlined functions, Mako tries to make them act that way), and +within an inheritance chain (each template in an inheritance +chain has a different notion of parent and next, which +are all stored in unique Context instances).

      +
        +
      • So what if I want to set values that are global to everyone +within a template request? - All you have to do is provide a +dictionary to your Context when the template first +runs, and everyone can just get/set variables from that. Lets +say its called attributes.

        +

        Running the template looks like:

        +
        output = template.render(attributes={})
        +
        +
        +

        Within a template, just reference the dictionary:

        +
        <%
        +    attributes['foo'] = 'bar'
        +%>
        +'foo' attribute is: ${attributes['foo']}
        +
        +
        +
      • +
      • Why can’t “attributes” be a built-in feature of the +Context? - This is an area where Mako is trying to make as +few decisions about your application as it possibly can. +Perhaps you don’t want your templates to use this technique of +assigning and sharing data, or perhaps you have a different +notion of the names and kinds of data structures that should +be passed around. Once again Mako would rather ask the user to +be explicit.

        +
      • +
      +
      +
      +

      Context Methods and Accessors?

      +

      Significant members of Context include:

      +
        +
      • context[key] / context.get(key, default=None) - +dictionary-like accessors for the context. Normally, any +variable you use in your template is automatically pulled from +the context if it isn’t defined somewhere already. Use the +dictionary accessor and/or get method when you want a +variable that is already defined somewhere else, such as in +the local arguments sent to a %def call. If a key is not +present, like a dictionary it raises KeyError.

        +
      • +
      • keys() - all the names defined within this context.

        +
      • +
      • kwargs - this returns a copy of the context’s +dictionary of variables. This is useful when you want to +propagate the variables in the current context to a function +as keyword arguments, i.e.:

        +
        ${next.body(**context.kwargs)}
        +
        +
        +
      • +
      • write(text) - write some text to the current output +stream.

        +
      • +
      • lookup - returns the TemplateLookup instance that is +used for all file-lookups within the current execution (even +though individual Template instances can conceivably have +different instances of a TemplateLookup, only the +TemplateLookup of the originally-called Template gets +used in a particular execution).

        +
      • +
      +
      +
      +
      +

      The Loop Context?

      +

      Within % for blocks, the reserved name loop +is available. loop tracks the progress of +the for loop and makes it easy to use the iteration state to control +template behavior:

      +
      <ul>
      +% for a in ("one", "two", "three"):
      +    <li>Item ${loop.index}: ${a}</li>
      +% endfor
      +</ul>
      +
      +
      +

      +New in version 0.7.

      +
      +

      Iterations?

      +

      Regardless of the type of iterable you’re looping over, loop always tracks +the 0-indexed iteration count (available at loop.index), its parity +(through the loop.even and loop.odd bools), and loop.first, a bool +indicating whether the loop is on its first iteration. If your iterable +provides a __len__ method, loop also provides access to +a count of iterations remaining at loop.reverse_index and loop.last, +a bool indicating whether the loop is on its last iteration; accessing these +without __len__ will raise a TypeError.

      +
      +
      +

      Cycling?

      +

      Cycling is available regardless of whether the iterable you’re using provides +a __len__ method. Prior to Mako 0.7, you might have generated a simple +zebra striped list using enumerate:

      +
      <ul>
      +% for i, item in enumerate(('spam', 'ham', 'eggs')):
      +  <li class="${'odd' if i % 2 else 'even'}">${item}</li>
      +% endfor
      +</ul>
      +
      +
      +

      With loop.cycle, you get the same results with cleaner code and less prep work:

      +
      <ul>
      +% for item in ('spam', 'ham', 'eggs'):
      +  <li class="${loop.cycle('even', 'odd')}">${item}</li>
      +% endfor
      +</ul>
      +
      +
      +

      Both approaches produce output like the following:

      +
      <ul>
      +  <li class="even">spam</li>
      +  <li class="odd">ham</li>
      +  <li class="even">eggs</li>
      +</ul>
      +
      +
      +
      +
      +

      Parent Loops?

      +

      Loop contexts can also be transparently nested, and the Mako runtime will do +the right thing and manage the scope for you. You can access the parent loop +context through loop.parent.

      +

      This allows you to reach all the way back up through the loop stack by +chaining parent attribute accesses, i.e. loop.parent.parent.... as +long as the stack depth isn’t exceeded. For example, you can use the parent +loop to make a checkered table:

      +
      <table>
      +% for consonant in 'pbj':
      +  <tr>
      +  % for vowel in 'iou':
      +    <td class="${'black' if (loop.parent.even == loop.even) else 'red'}">
      +      ${consonant + vowel}t
      +    </td>
      +  % endfor
      +  </tr>
      +% endfor
      +</table>
      +
      +
      +
      <table>
      +  <tr>
      +    <td class="black">
      +      pit
      +    </td>
      +    <td class="red">
      +      pot
      +    </td>
      +    <td class="black">
      +      put
      +    </td>
      +  </tr>
      +  <tr>
      +    <td class="red">
      +      bit
      +    </td>
      +    <td class="black">
      +      bot
      +    </td>
      +    <td class="red">
      +      but
      +    </td>
      +  </tr>
      +  <tr>
      +    <td class="black">
      +      jit
      +    </td>
      +    <td class="red">
      +      jot
      +    </td>
      +    <td class="black">
      +      jut
      +    </td>
      +  </tr>
      +</table>
      +
      +
      +
      +
      +

      Migrating Legacy Templates that Use the Word “loop”?

      +

      +Changed in version 0.7: The loop name is now reserved in Mako, +which means a template that refers to a variable named loop +won’t function correctly when used in Mako 0.7.

      +

      To ease the transition for such systems, the feature can be disabled across the board for +all templates, then re-enabled on a per-template basis for those templates which wish +to make use of the new system.

      +

      First, the enable_loop=False flag is passed to either the TemplateLookup +or Template object in use:

      +
      lookup = TemplateLookup(directories=['/docs'], enable_loop=False)
      +
      +
      +

      or:

      +
      template = Template("some template", enable_loop=False)
      +
      +
      +

      An individual template can make usage of the feature when enable_loop is set to +False by switching it back on within the <%page> tag:

      +
      <%page enable_loop="True"/>
      +
      +% for i in collection:
      +    ${i} ${loop.index}
      +% endfor
      +
      +
      +

      Using the above scheme, it’s safe to pass the name loop to the Template.render() +method as well as to freely make usage of a variable named loop within a template, provided +the <%page> tag doesn’t override it. New templates that want to use the loop context +can then set up <%page enable_loop="True"/> to use the new feature without affecting +old templates.

      +
      +
      +
      +

      All the Built-in Names?

      +

      A one-stop shop for all the names Mako defines. Most of these +names are instances of Namespace, which are described +in the next section, Namespaces. Also, most of +these names other than context, UNDEFINED, and loop are +also present within the Context itself. The names +context, loop and UNDEFINED themselves can’t be passed +to the context and can’t be substituted – see the section Reserved Names.

      +
        +
      • context - this is the Context object, introduced +at Context.
      • +
      • local - the namespace of the current template, described +in Built-in Namespaces.
      • +
      • self - the namespace of the topmost template in an +inheritance chain (if any, otherwise the same as local), +mostly described in Inheritance.
      • +
      • parent - the namespace of the parent template in an +inheritance chain (otherwise undefined); see +Inheritance.
      • +
      • next - the namespace of the next template in an +inheritance chain (otherwise undefined); see +Inheritance.
      • +
      • caller - a “mini” namespace created when using the +<%call> tag to define a “def call with content”; described +in Calling a Def with Embedded Content and/or Other Defs.
      • +
      • loop - this provides access to LoopContext objects when +they are requested within % for loops, introduced at The Loop Context.
      • +
      • capture - a function that calls a given def and captures +its resulting content into a string, which is returned. Usage +is described in Filtering and Buffering.
      • +
      • UNDEFINED - a global singleton that is applied to all +otherwise uninitialized template variables that were not +located within the Context when rendering began, +unless the Template flag strict_undefined +is set to True. UNDEFINED is +an instance of Undefined, and raises an +exception when its __str__() method is called.
      • +
      • pageargs - this is a dictionary which is present in a +template which does not define any **kwargs section in its +<%page> tag. All keyword arguments sent to the body() +function of a template (when used via namespaces) go here by +default unless otherwise defined as a page argument. If this +makes no sense, it shouldn’t; read the section +The body() Method.
      • +
      +
      +

      Reserved Names?

      +

      Mako has a few names that are considered to be “reserved” and can’t be used +as variable names.

      +

      +Changed in version 0.7: Mako raises an error if these words are found passed to the template +as context arguments, whereas in previous versions they’d be silently +ignored or lead to other error messages.

      + +
      +
      +
      +

      API Reference?

      +
      +
      +class mako.runtime.Context(buffer, **data)?
      +

      Bases: object

      +

      Provides runtime namespace, output buffer, and various +callstacks for templates.

      +

      See The Mako Runtime Environment for detail on the usage of +Context.

      +
      +
      +get(key, default=None)?
      +

      Return a value from this Context.

      +
      + +
      +
      +keys()?
      +

      Return a list of all names established in this Context.

      +
      + +
      +
      +kwargs?
      +

      Return the dictionary of keyword arguments associated with this +Context.

      +
      + +
      +
      +locals_(d)?
      +

      Create a new Context with a copy of this +Context‘s current state, updated with the given dictionary.

      +
      + +
      +
      +lookup?
      +

      Return the TemplateLookup associated +with this Context.

      +
      + +
      +
      +pop_caller()?
      +

      Pop a caller callable onto the callstack for this +Context.

      +
      + +
      +
      +push_caller(caller)?
      +

      Push a caller callable onto the callstack for +this Context.

      +
      + +
      +
      +write(string)?
      +

      Write a string to this Context object’s +underlying output buffer.

      +
      + +
      +
      +writer()?
      +

      Return the current writer function.

      +
      + +
      + +
      +
      +class mako.runtime.LoopContext(iterable)?
      +

      Bases: object

      +

      A magic loop variable. +Automatically accessible in any % for block.

      +

      See the section The Loop Context for usage +notes.

      +
      +
      parent -> LoopContext or None
      +
      The parent loop, if one exists.
      +
      index -> int
      +
      The 0-based iteration count.
      +
      reverse_index -> int
      +
      The number of iterations remaining.
      +
      first -> bool
      +
      True on the first iteration, False otherwise.
      +
      last -> bool
      +
      True on the last iteration, False otherwise.
      +
      even -> bool
      +
      True when index is even.
      +
      odd -> bool
      +
      True when index is odd.
      +
      +
      +
      +cycle(*values)?
      +

      Cycle through values as the loop progresses.

      +
      + +
      + +
      +
      +class mako.runtime.Undefined?
      +

      Bases: object

      +

      Represents an undefined value in a template.

      +

      All template modules have a constant value +UNDEFINED present which is an instance of this +object.

      +
      + +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/search.html b/lib/mako-0.7.2/doc/search.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/search.html @@ -0,0 +1,160 @@ + + + + + + + Search + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Search + + +

      + + Search + +

      +
      + +
      + +
      + + +
      + + + + + + +
      +

      Enter Search Terms:

      + +
      + +
      + + + +
      + +
      + + + +
      + +
      + + +
      + + + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/searchindex.js b/lib/mako-0.7.2/doc/searchindex.js new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/searchindex.js @@ -0,0 +1,1 @@ +Search.setIndex({objects:{RichTraceback:{records:[8,0,1,""],reverse_traceback:[8,0,1,""],source:[8,0,1,""],lineno:[8,0,1,""],reverse_records:[8,0,1,""],error:[8,0,1,""],message:[8,0,1,""]},"mako.exceptions":{text_error_template:[8,3,1,""],RichTraceback:[8,2,1,""],html_error_template:[8,3,1,""]},"mako.lookup.TemplateLookup":{put_template:[8,1,1,""],get_template:[8,1,1,""],put_string:[8,1,1,""],adjust_uri:[8,1,1,""],filename_to_uri:[8,1,1,""]},"mako.runtime.Context":{write:[9,1,1,""],get:[9,1,1,""],keys:[9,1,1,""],push_caller:[9,1,1,""],writer:[9,1,1,""],pop_caller:[9,1,1,""],locals_:[9,1,1,""],lookup:[9,0,1,""],kwargs:[9,0,1,""]},"mako.lookup.TemplateCollection":{get_template:[8,1,1,""],adjust_uri:[8,1,1,""],has_template:[8,1,1,""],filename_to_uri:[8,1,1,""]},"mako.runtime.ModuleNamespace":{filename:[3,0,1,""]},"mako.cache.CacheImpl":{invalidate:[6,1,1,""],get_or_create:[6,1,1,""],pass_context:[6,0,1,""],set:[6,1,1,""],get:[6,1,1,""]},"mako.runtime.LoopContext":{cycle:[9,1,1,""]},"mako.cache":{register_plugin:[6,3,1,""],CacheImpl:[6,2,1,""],Cache:[6,2,1,""]},"mako.runtime.Namespace":{include_file:[3,1,1,""],template:[3,0,1,""],get_cached:[3,1,1,""],get_namespace:[3,1,1,""],cache:[3,0,1,""],uri:[3,0,1,""],module:[3,0,1,""],filename:[3,0,1,""],context:[3,0,1,""],get_template:[3,1,1,""],attr:[3,0,1,""]},"mako.lookup":{TemplateLookup:[8,2,1,""],TemplateCollection:[8,2,1,""]},"mako.runtime.TemplateNamespace":{uri:[3,0,1,""],module:[3,0,1,""],filename:[3,0,1,""]},"mako.runtime":{capture:[3,3,1,""],Undefined:[9,2,1,""],Namespace:[3,2,1,""],ModuleNamespace:[3,2,1,""],supports_caller:[3,3,1,""],Context:[9,2,1,""],LoopContext:[9,2,1,""],TemplateNamespace:[3,2,1,""]},"mako.ext.beaker_cache":{BeakerCacheImpl:[6,2,1,""]},"mako.cache.Cache":{invalidate:[6,1,1,""],set:[6,1,1,""],invalidate_body:[6,1,1,""],get:[6,1,1,""],invalidate_closure:[6,1,1,""],invalidate_def:[6,1,1,""],starttime:[6,0,1,""],put:[6,1,1,""],get_or_create:[6,1,1,""],id:[6,0,1,""],impl:[6,0,1,""]},"mako.template.Template":{render_context:[8,1,1,""],code:[8,0,1,""],render:[8,1,1,""],source:[8,0,1,""],render_unicode:[8,1,1,""],get_def:[8,1,1,""]},"mako.template":{DefTemplate:[8,2,1,""],Template:[8,2,1,""]}},terms:{interchang:4,four:[3,5],prefix:[6,9],dirnam:8,"_my_cache_work":6,typeerror:9,swap:6,under:[8,6,7],everi:[3,5],long_term:6,jack:8,voix:7,appar:[2,3],vast:7,pagearg:[0,9,3,7],get_templ:[8,6,3,7],buildtabl:0,cache_kei:6,direct:[0,8,6,3,5],batch:2,outputpath:8,second:[0,6,2],even:[5,9,7,4],"new":[0,8,9,6,4],ever:[3,7],metadata:5,widget:0,behavior:[8,2,9],here:[2,7,4,5,6,3,8,9],met:0,path:[8,6,3],interpret:[0,8,7],tagfilt:2,portabl:0,txt:[8,7,5],describ:[0,2,3,4,5,7,8,9],would:[0,2,4,6,7,8,9],call:[0,1,2,3,4,5,6,7,8,9],recommend:3,type:[0,5,6,7,8,9],until:8,relat:[8,6,7],notic:0,pkg_resourc:6,must:[0,8,6,3,7],join:7,setup:[8,6,4],work:[0,2,7,4,6,3,8,9],root:8,overrid:[7,4,6,3,8,9],give:[0,3],indic:[1,9,5],somefil:3,do_something_speci:6,want:[0,2,7,4,5,3,6,9],end:[5,2,4],quot:7,ordinari:3,output_encod:[8,7],how:[0,5,6,3,8,9],cheetah:7,updat:[8,9],module_filenam:8,recogn:[3,4],lai:0,after:[8,6,2,3,9],befor:[2,7,4,5,6,3,8],attempt:7,third:6,recompil:[8,6],maintain:[8,6],environ:[8,1,2,9,5],exclus:8,order:[8,6,5,7,4],origin:[2,7,6,3,8,9],somedata:0,over:[2,3,9],fall:6,becaus:[0,2,7,4],demarc:0,affect:9,flexibl:[5,2,4],myfil:5,streamlin:4,fix:[8,6,3],"__class__":8,better:[6,9],persist:6,easier:6,them:[0,2,4,3,8,9],thei:[0,2,4,5,7,8,9],safe:[9,7],default_filt:[8,2,7],jinja2:[0,5],html_error_templ:8,getvalu:[8,2],myghti:7,timeout:6,each:[0,4,5,6,7,8,9],side:[0,2,5],mean:[0,2,7,5,6,3,8,9],enorm:0,cacheimpl:[8,6],extract:8,expression_filt:2,unbound:8,goe:5,newli:6,content:[0,1,2,4,5,6,3,8,9],sane:0,mypackag:2,multilin:5,bottommost:4,free:3,standard:[6,7],argument:[0,1,2,3,5,6,7,8,9],traceback:8,moment:8,filter:[0,1,2,5,7,8,9],heck:[8,1,7],isn:9,text_error_templ:8,onto:[9,5],user:[8,6,9,7,5],rang:[0,5],render:[0,1,2,3,4,5,6,7,8,9],restrict:[0,4],unlik:7,alreadi:[8,9,4],wrapper:2,wasn:[9,4],agre:4,primari:8,lister:0,top:[0,2,4,3,6,9],sometim:[5,4],stack:[8,2,9],cache_region:6,too:[2,4],similarli:[0,7],john:0,consol:7,conson:9,namespac:[0,1,2,4,5,6,3,8,9],tool:6,setuptool:[8,6],somewhat:[0,2],some_namespac:3,myfilt:2,target:[0,2],keyword:[0,7,4,5,3,8,9],provid:[0,2,4,5,6,3,8,9],expr:[0,3],project:8,matter:4,minut:6,thu:8,mini:9,fashion:6,close:[0,8,3,5],runner:8,modern:6,htmlentityreplac:8,raw:[8,7],manner:2,templatelookup:[1,2,7,6,3,8,9],minu:6,latter:7,shall:4,usernam:[0,5],object:[0,2,3,4,5,6,7,8,9],regular:[0,1,2,3,4,5,7,8],phase:8,invalidate_closur:6,simplic:2,paradigm:4,don:[0,6,9,7,4],doc:[0,8,9,7,5],flow:5,doe:[0,7,4,5,3,9],declar:[0,1,2,4,5,3,8],tracelin:8,notion:9,opposit:4,"__str__":9,syntax:[0,1,2,8,5],get_resourc:5,involv:4,absolut:[0,7],layout:[0,8,4],acquir:[6,7],configur:[8,6,3,4],stop:[9,5],report:8,bar:[0,2,5,3,8,9],emb:[3,7,5],reload:8,short_term:6,black:9,elimin:7,result:[0,8,2,9,5],respons:[6,9,4],basemost:4,awar:[8,9,7],databas:0,urllib:2,implicit:[6,9],simplest:5,pybabel:8,awai:4,approach:[9,7,4],attribut:[0,1,2,4,5,6,3,8,9],preprocessor:8,easi:[2,9],howev:[0,6,3,7,4],against:[8,5],facet:9,logic:2,col:0,dogpil:6,guid:8,assum:[8,7],templatenamespac:3,three:[9,5],been:[8,6,2,3,7],accumul:5,much:[0,5,7,4],basic:[0,1,7,5,3,8],"__len__":9,quickli:7,disable_unicod:[8,2,7],ani:[0,2,3,4,5,6,7,8,9],multithread:6,lift:4,ident:8,servic:[6,7,5],properti:[8,3],calcul:8,printabl:7,kwarg:[8,6,9,3],somekei:6,sever:3,mako:[0,1,2,3,4,5,6,7,8,9],quand:7,perform:[8,2,3,7],make:[0,2,3,4,5,6,7,8,9],transpar:9,push_cal:9,complet:[8,3,4],rais:[0,8,9,7],caller_stack:[3,7],scenario:[0,8,9,3],get_cach:3,hypothet:4,inherit:[0,1,4,5,6,3,8,9],thi:[0,2,3,4,5,6,7,8,9],endif:[0,9,5],programm:7,everyth:9,pagecontrol:0,left:[8,2],identifi:[8,6],just:[0,2,3,4,5,7,8,9],invalidate_bodi:6,unbuff:2,yet:[6,3],languag:[0,7,5],previous:[8,3],enable_loop:[8,9],pygmentplugin:8,ham:9,ell:7,had:7,input_encod:[8,7],board:9,els:[8,6,9,5],gave:8,opt:[8,6],applic:[8,2,9,5],mayb:4,background:7,specif:[0,2,4,5,6,3,8,9],arbitrari:[6,5],manual:8,babelplugin:8,underli:[0,2,4,5,6,3,8,9],right:[0,2,9,7,5],old:9,deal:[9,7,5],excerpt:8,maxim:[6,7],percentag:8,intern:[8,6,2,7,9],subclass:[0,8,6],track:9,condit:[0,5,4],foo:[0,2,7,5,3,8,9],plu:8,bold:2,relationship:3,post:[0,8],"super":[6,3,7,4],plug:6,slightli:[3,7],surround:5,produc:[0,1,2,4,5,7,8,9],rudiment:[8,6],encod:[8,1,2,7],down:[6,7],lieu:8,wrap:[0,1,5,4],storag:7,accordingli:8,wai:[0,1,2,3,4,5,6,7,8,9],support:[0,7,5,6,3,8],transform:2,why:9,avail:[0,2,3,4,5,6,7,8,9],overhead:7,head:[0,8,4],form:[0,3,5],offer:[7,5],forc:8,get_def:[0,8,2],taken:[8,6,3],"true":[0,2,7,5,6,3,8,9],attr:[3,4],tell:5,emit:5,trim:[2,5],featur:[5,9,4],classic:[3,5],petit:7,"abstract":8,exist:[0,7,5,6,3,8,9],check:[8,5,9,7,4],when:[0,2,3,4,5,6,7,8,9],entrypoint:6,intend:[2,3],stringio:[8,9,7],intent:2,consid:[8,9],receiv:[0,2,3,5],faster:7,cache_en:[8,6],htdoc:8,ignor:[9,5],time:[0,1,2,4,6,8],push:9,serious:4,backward:6,concept:[0,8,5],chain:[5,9,3,4],skip:8,consum:[6,5],signific:[9,5],subcompon:0,row:0,decid:[9,5],middl:[5,2,4],depend:[8,5],mainlayout:[0,4],intermedi:4,decis:[9,7,4],sourc:[8,7,5],string:[2,7,5,6,3,8,9],word:[8,9,4],level:[0,1,2,3,4,5,6,7,8,9],did:4,iter:[0,9],item:[0,9,5],mycomp:6,quick:[0,5],lever:7,div:[0,8,3,4],dir:[8,6],slower:7,sign:5,namepacenam:0,appear:[2,9,5],current:[0,4,5,3,8,9],deriv:[6,2,7],gener:[0,2,3,4,5,6,7,8,9],address:[8,6],along:[6,3],toolbar:[5,4],bot:9,behav:0,commonli:[6,7,4],semant:[0,4],regardless:[0,9,4],extra:[5,4],modul:[0,1,2,3,4,5,6,7,8,9],prefer:7,render_bodi:[8,2,7,9],fake:5,marker:5,instal:6,callstack:9,memori:[8,6,5],sake:2,perl:5,live:6,handler:8,scope:[0,4,5,3,6,9],prep:9,chapter:[0,1,2,4,7,8],afford:8,accept:[2,7,5,6,3,8],render_:9,myexpress:2,mylookup:[8,7],fly:7,graphic:7,uniqu:[6,9,4],whatev:[8,9,3,7],purpos:[8,7],stream:[8,9,3,7,5],backslash:5,occur:[0,8,6],alwai:[0,9,7,4],differenti:9,multipl:[0,1,6,7,4],get:[2,7,4,5,6,3,8,9],modulenam:6,write:[2,7,5,6,3,8,9],pure:[3,7,5],cache_xyz:6,somevalu:6,map:8,product:8,usabl:0,mai:[2,7,5,6,3,8,9],data:[0,7,6,3,8,9],goal:2,practic:4,explicit:[0,7,5,3,6,9],format_except:8,inform:[8,3,7,5],"switch":9,preced:[8,5,3,7,4],combin:9,callabl:[0,2,5,6,3,8,9],extractor:8,still:[0,7,4],mainli:3,dynam:5,entiti:2,conjunct:8,group:[6,3],platform:8,jit:9,push_buff:2,main:[0,2,7,4,3,8,9],non:[8,9,7,5],recal:4,francoi:8,contriv:8,supersed:6,initi:0,underneath:6,therebi:3,now:[5,9,7,4],pop_fram:7,term:6,name:[0,1,2,3,4,5,6,7,8,9],drop:5,separ:[0,6,2,4],"__str":7,compil:[8,6,9,5],replac:[8,6,2,7],individu:[0,8,9,6],arg3:3,arg4:3,continu:[8,7,5],zebra:9,happen:[9,3,7],accomplish:[8,6],space:[0,6,5],intermix:4,correct:3,earlier:[6,7],migrat:[8,9],"byte":[8,7],care:[6,9,3,7],thing:[0,5,9,7,4],place:[0,8,5,6,4],think:9,first:[2,7,4,5,3,6,9],oper:[0,2,7,5,3,8,9],suspend:5,directli:[0,2,5,6,3,8],onc:[0,5,9,4],arrai:2,yourself:[8,7],walkthrough:0,textual:[8,2,4],custom:[0,2,7,5,6,3,8],open:[5,7,4],size:8,given:[0,2,4,6,3,8,9],silent:9,convent:0,caught:8,checker:9,necessarili:9,white:4,conveni:6,programat:8,copi:[9,3],specifi:[1,2,4,6,7,8,9],enclos:[0,9],mostli:[8,6,9,3],than:[2,4,5,7,6,9],serv:[8,7],"__m_local":7,were:[9,3,7],posit:3,seri:[8,6,7],pre:8,sai:[0,1,4,7,8,9],put_str:8,anywher:[0,5],deliv:[2,3],notimplementederror:8,techniqu:9,pop_cal:9,note:[0,2,7,4,6,3,8,9],take:[0,2,7,4,5,3],blunt:6,sure:5,trace:8,normal:[0,2,5,7,8,9],buffer:[1,2,7,5,3,8,9],subdef:0,synonym:[6,3],later:[6,5],highlight:8,templatenam:8,runtim:[1,2,4,5,6,3,8,9],preambl:8,shop:9,imaginez:7,delta:3,permiss:8,hack:9,xml:[8,2,5],onli:[0,2,4,5,6,7,8,9],explicitli:[8,9,3,7],state:[0,9,7],dict:7,overwritten:6,variou:[2,7,5,3,8,9],distinctli:4,dyn:3,tailor:0,requir:[0,6,3,7,5],where:[0,2,3,4,5,6,7,8,9],summari:5,wonder:5,nestabl:0,enumer:9,between:[0,9],"import":[0,2,7,5,6,3,8,9],across:[6,9],parent:[0,1,4,6,3,8,9],comp:3,cycl:9,my_dogpile_region:6,uncondition:7,come:[0,4,5,6,7,8],cache_url:[8,6],region:6,mani:[9,5],pow:5,pot:9,inspir:5,pop:[6,2,9],colon:[6,5],encoding_error:[8,7],ultim:[3,4],dessin:7,markedli:7,resolut:[8,3],those:[0,5,6,3,8,9],"case":[0,2,3,4,5,6,7,8,9],mouton:7,invok:[0,8,5,4],cannot:[0,8,7],invoc:4,advantag:[8,3,7,4],stdout:8,threadsaf:6,destin:8,shutil:8,ascii:7,"__init__":6,develop:7,author:9,same:[0,7,5,6,3,8,9],binari:7,epoch:6,html:[0,2,3,4,5,6,7,8],document:[8,6,5,7,4],breakdown:4,finish:4,utf8:[2,7],nest:[0,1,2,4,6,9],capabl:[8,6],vowel:9,improv:[8,7,5],extern:[0,6,4],moder:8,facad:6,without:[6,9,3,4],model:0,roughli:5,execut:[0,2,4,5,3,6,9],rest:[6,5,4],aspect:[7,5],speed:[2,7],versu:[8,3],except:[0,1,2,5,6,8,9],littl:[0,8,9],treatment:7,role:3,earli:[1,5],ream:7,around:[8,2,9],read:[9,7,5],moi:7,world:[0,7,5,3,8,9],use_pag:2,serve_templ:8,integ:[0,6,7],server:[8,6,5],either:[4,5,6,7,8,9],output:[0,1,2,3,4,5,7,8,9],manag:[6,9],somefunct:3,definit:[0,2,3,4],disait:7,inject:8,refer:[0,1,2,3,4,5,6,7,8,9],some_templ:8,power:5,garbag:6,pass_context:6,starttim:6,found:[0,9,5],"__name__":[8,6],"throw":[6,9],central:[0,2,9,5],act:[8,9],mytempl:[8,6,7],routin:8,overrod:4,strip:2,your:[0,2,4,5,3,9],msgstr:8,fast:8,her:7,area:[0,5,9,7,4],aren:[0,7],start:[0,6],compliant:7,interfac:6,lot:5,strictli:7,programmat:[0,1,2,7,6,9],tupl:8,regard:7,jut:9,illus:7,pull:[0,8,9,3],possibl:[0,6,2,9],"default":[0,2,3,4,5,6,7,8,9],unusu:8,embed:[0,8,9,3,5],creat:[0,7,5,6,3,8,9],multibyt:8,certain:[8,2,7],somedef:[0,6,2,3,5],intro:0,decreas:3,file:[0,1,3,4,5,6,7,8,9],again:[0,9],gettext:8,field:8,valid:5,you:[0,2,3,4,5,6,7,8,9],symbol:5,reduc:2,directori:[8,6,2,7,9],descript:8,mimic:8,potenti:4,escap:[0,1,2,7,5],represent:[8,5],all:[0,1,2,3,4,5,6,7,8,9],illustr:[8,2,4],scalar:3,abil:[8,6,7,5],follow:[0,4,5,3,8,9],program:[7,5],objnam:6,introduc:[0,5,9,3,4],sound:[5,4],"pla\u00eet":7,liter:[8,3,7],fals:[8,6,9],util:8,mechan:[6,5,4],failur:9,veri:[0,8,6,4],condition:3,list:[0,2,4,5,6,7,8,9],adjust:[8,3,5],small:8,pbj:9,aptli:8,design:2,nsname:5,pass:[0,7,4,5,6,3,8,9],further:5,what:[0,1,3,4,5,7,8,9],sub:[0,5],section:[0,4,6,3,8,9],advanc:8,abl:9,brief:8,version:[0,2,7,4,5,3,9],deepli:0,method:[0,1,2,3,4,5,6,7,8,9],contrast:[0,7,4],full:[8,5],themselv:[0,4,5,3,6,9],shouldn:9,inher:2,modifi:[0,8,7,4],valu:[0,2,7,5,6,3,8,9],search:[8,1],memcach:6,prior:[2,7,9],real:[8,5],render_mydef:9,via:[0,7,4,6,3,8,9],transit:9,ask:9,href:0,pythagorean:5,establish:[8,9],select:[7,4],mylib:5,distinct:8,regist:6,two:[0,2,3,4,5,6,7,8,9],push_fram:7,minor:8,more:[0,2,3,4,5,6,7,8,9],desir:[8,3,7],flag:[2,7,5,6,3,8,9],stick:[0,9,7,5],particular:[8,6,9,3,4],known:[0,3],cach:[0,1,2,5,6,3,8,9],none:[8,6,2,3,9],remain:[0,9],learn:7,def:[0,1,2,3,4,5,6,7,8,9],someobject:3,userbas:7,share:[0,9],templat:[0,1,2,3,4,5,6,7,8,9],sharp:0,wsgiutil:8,cours:9,newlin:[1,5],rather:9,anoth:[0,7,5,3,8,9],render_unicod:[8,7],simpl:[0,8,9,6,5],css:8,regener:8,resourc:[8,4],referenc:[0,9,3],variant:5,catalog:8,associ:[6,9],"short":6,footer:[5,4],confus:7,caus:[8,2,3,9],egg:9,help:[8,6,7],singleton:9,through:[8,9,7],paramet:[8,6,3,7],style:[0,7],might:[9,3,5],wouldn:[3,5],good:6,"return":[0,1,2,3,5,6,7,8,9],timestamp:6,framework:[8,1],ninja:4,achiev:[0,9,4],fulli:[8,2],unicod:[8,1,2,7],locals_:9,hard:[5,9,7,4],idea:[5,4],procedur:6,realli:7,expect:[0,5,7,4],beyond:[0,6],orient:[0,4],sometempl:6,lineno:8,print:[0,8,7],proxi:3,ast:7,guess:7,reason:[9,7],base:[1,2,4,5,6,3,8,9],put:[6,9,4],basi:[6,9],thrown:[8,6],thread:6,perhap:[0,9,5],assign:[0,8,9,5],major:[9,7],number:[0,8,9,6,5],done:[8,7],defnam:[0,5],blank:9,miss:[8,2,9],differ:[0,4,6,3,8,9],interact:[3,7],least:[8,3],calling_uri:3,statement:[0,8,5],natur:2,scheme:[0,8,9,7],store:[8,6,2,7,9],option:[7,5,6,3,8,9],modulenamespac:3,part:[6,9,3,4],pars:[8,7,5],kind:[2,4,5,6,7,8,9],whenev:[8,7,4],remot:[0,3],remov:[3,7],str:[8,2,7,9],arrang:5,toward:[0,4],grei:4,cleaner:9,mytmpl:8,get_namespac:3,comp2:3,packag:[6,5],comp1:3,expir:6,deftempl:[0,8],jour:7,built:[0,1,2,3,4,5,7,8,9],equival:[0,2,7,5,3,6],self:[0,4,5,6,3,8,9],undeclar:8,also:[0,2,3,4,5,6,7,8,9],build:[0,4],distribut:8,filesystem:[8,6,3],reach:[8,9],disgard:7,most:[0,7,4,5,6,3,8,9],plai:[3,7],jsp:5,ext:[8,6],fastencodingbuff:7,wsgi:8,particularli:3,find:[8,9,5],mydef:0,coerc:7,pretti:[7,5],writer:9,hit:[2,7],"__file__":3,express:[0,1,2,3,4,5,7,8,9],nativ:7,common:[8,1,7],set:[2,7,5,6,3,8,9],genshi:5,dump:[3,7],see:[0,7,5,6,3,8,9],dumb:7,arg:[0,2,5,6,3,8],reserv:9,whatsoev:7,someth:[0,2,7],topmost:[5,9,3,4],won:[8,9,4],altern:[8,9,7],signatur:[0,3],syntact:5,numer:5,popul:6,both:[0,2,4,7,8,9],last:[8,9],put_templ:8,alor:7,context:[0,1,2,3,5,6,7,8,9],whole:[0,2,3,4],load:[8,3,5],simpli:[2,4],bell:7,arbitrarili:0,header:[0,8,5,6,4],uniniti:9,param:5,suppli:[3,5],frobnizzl:5,throughout:3,backend:[6,3],empti:[2,7],accessor:[6,9,3,4],strategi:6,error_handl:8,imag:[8,7],great:[3,7],understand:7,func:3,xa9:7,look:[0,7,4,6,3,8,9],get_or_cr:6,straight:[8,7],histor:6,"while":[0,8,5,2,4],abov:[0,2,3,4,5,6,7,8,9],error:[0,8,9,7],anonym:[0,6,5],everyon:9,loop:[0,1,8,9,5],pylon:8,propag:[8,9,5],richtraceback:8,vou:7,itself:[0,2,3,4,5,6,7,8,9],decor:[1,2,3],minim:6,decod:[2,7],conflict:6,x80:7,wherea:[0,9,7,5],has_templ:8,stripe:9,pop_buff:2,typic:[8,6],recent:8,travers:3,task:6,older:0,cachemanag:6,entri:[8,6],somev:[9,3],elem:5,picki:7,endfor:[0,9,5],construct:[0,7,4,5,6,3,8],burden:7,sidebar:0,adjust_uri:8,msgid:8,theorem:5,input:[0,2,7],subsequ:6,format:[0,8,3,7,5],game:7,bit:[0,8,9],characterist:5,creation_funct:6,semi:6,whitespac:[0,2,5],resolv:8,collect:[8,6,9,3,7],"boolean":8,popular:8,encount:4,often:3,creation:[0,8,2,6],some:[0,2,3,4,5,6,7,8,9],back:[8,9,7,4],global:[0,6,9,3,4],understood:6,sampl:8,mirror:8,surpris:7,modulepath:6,though:[6,9,7,4],pep:7,per:[6,9,7,5],namespace_nam:3,substitut:[8,1,2,9,5],larg:4,slash:[3,5],leftmost:2,cgi:[2,7],buffer_filt:8,previou:[0,8,9,4],run:[8,9,3,7],namespacenam:[0,5],reverse_traceback:8,step:[0,8,7],loopcontext:9,from:[0,1,2,3,4,5,6,7,8,9],mynamespac:[3,5],exc_info:8,block:[0,1,2,4,5,6,9],within:[0,2,3,4,5,6,7,8,9],toplevelnotfound:8,ensur:[6,3,7],chang:[6,9,4],run_wsgi:8,span:[0,4],reverse_index:9,spam:9,bodi:[0,1,4,5,6,3,8,9],stylesheet:8,"long":[9,5],beaker_cach:6,includ:[0,5,6,3,8,9],suit:4,myfunc:5,properli:7,templatelookupexcept:8,link:8,translat:8,newer:[0,8],atom:8,line:[8,5,7,4],info:8,concaten:2,utf:[8,2,7],consist:5,caller:[0,2,3,9],my_tag:3,myescap:2,similar:[0,2,3,4,5,7,8,9],impl:6,constant:9,doesn:[0,9,3,4],repres:[0,5,6,7,8,9],modulename_cal:8,titl:[0,5,4],invalid:6,codec:[8,7],accountdata:0,draw:2,clean:[8,6],nightmar:7,bytestring_passthrough:8,xb4le:7,cache_typ:[8,6,5],depth:9,far:[8,5,7,4],hello:[0,8,3,7,5],code:[0,2,7,5,3,8,9],templatetext:[2,7],send:[2,7,4,3,8,9],sens:9,sent:[2,9,3,5],tri:[0,8,9],magic:[9,7],"try":[8,2,9,7,5],dealt:8,pleas:5,impli:8,cfg:8,odd:9,append:8,compat:[8,6,3],index:[1,4,5,3,8,9],compar:[8,7],xa9veil:7,access:[0,1,4,5,6,3,8,9],can:[0,2,3,4,5,6,7,8,9],len:5,closur:0,let:[0,8,9,4],becom:[8,3,7],sinc:[0,9,3,7,4],filesystem_check:8,convert:[8,6,7],convers:7,conceiv:9,ctx:8,implement:[0,8,6,4],appli:[0,2,7,5,3,8,9],approxim:8,mystuff:0,api:[1,2,6,3,8,9],immut:9,register_plugin:6,metaphor:4,commun:[0,9],next:[0,1,2,3,4,5,6,7,8,9],implic:7,few:9,trail:2,beakercacheimpl:6,account:0,retriev:6,augment:[0,1,4],obvious:4,control:[0,1,2,4,5,8,9],accountnam:0,process:[6,7,5],lock:6,slim:6,tag:[0,1,2,4,5,6,3,8,9],layoutdata:0,nari:7,instead:[0,2,7,4,3,8],templatecollect:8,overridden:[0,6,3,4],class_:4,tack:3,philosophi:9,callable_:[8,3],essenti:[6,3,7],correspond:[8,6,9,3,4],element:[0,8,9,7,5],issu:[0,8,7],allow:[0,2,3,4,5,6,7,8,9],elif:5,move:8,comma:[0,2],bunch:3,outer:0,chosen:6,myproj:8,bye:0,handl:[0,1,5,6,7,8,9],handi:3,"r\u00e9veill\u00e9":7,relativeto:8,somewher:[8,9,7],anyth:[0,7,4],nameerror:[8,9],mode:7,disregard:8,pygment:8,intellig:7,filehandl:7,our:[0,8,6,4],special:[8,6,2,9,5],out:[0,4,5,6,7,8],variabl:[0,4,5,3,8,9],contigu:5,categori:3,rel:[8,3],red:9,insid:[0,4,5,6,3,8],call_my_object:7,standalon:8,dictionari:[8,6,9,3],releas:[6,3,5],indent:5,xc3:7,could:4,lexer:[8,7,5],keep:0,outsid:[0,9,3,7,4],strict:8,system:[0,8,9,6,4],messag:[8,9],attach:3,"final":[2,7,4],cache_dir:[8,6],accompani:8,exactli:[0,4],filename_to_uri:8,structur:[1,9,5],charact:[8,7,5],simplecacheimpl:6,have:[0,2,3,4,5,6,7,8,9],tabl:[0,1,9],need:[0,7,4,6,3,8,9],turn:[2,7,4],babel:8,outward:8,builtin:7,best:5,which:[0,2,3,4,5,6,7,8,9],singl:[0,2,4,5,6,7,8],unless:[9,7],who:7,segment:7,"class":[0,7,4,6,3,8,9],url:[8,6,2,5],gather:7,request:[8,6,9],uri:[8,3,5],pipe:2,determin:[6,7],"_cach":6,fact:[0,7,4],render_context:8,dbm:6,text:[0,2,5,6,7,8,9],cache_timeout:[0,6],anywai:8,locat:[8,9,3,7],should:[8,6,9,3],suppos:[0,6],local:[0,2,5,6,3,8,9],meant:4,familiar:[0,5],bean:8,cache_:6,increas:8,cstringio:[8,7],enabl:[8,6,9,5],organ:[3,4],current_sect:5,stuff:[3,5],integr:[8,1,4],contain:[0,7,5,6,3,8],view:8,reverse_record:8,legaci:[8,9],collection_s:8,pinard:8,flip:0,bytestr:8,mako_modul:8,polymorph:5,correctli:9,pattern:8,written:[8,5,4],progress:9,neither:6,email:5,jot:9,kei:[8,6,9,3,7],module_directori:[8,6],tempfil:8,job:2,entir:[0,1,2,3,5,7,8],joe:5,cache_arg:[8,6],addit:[0,2,4,5,6,3,8],plugin:[6,1],etc:[0,8,9,6,5],instanc:[8,9,3,5],freeli:9,comment:[8,1,7,5],guidelin:6,mako_cach:6,respect:5,addition:[8,7,4],compon:[6,9,3],include_fil:3,treat:7,immedi:[8,5,9,7,4],upcom:6,togeth:4,present:[0,7,4,6,3,8,9],determinist:2,therefor:[8,5,3,4],plain:[0,8,3,7,5],contextu:0,defin:[0,1,2,3,4,5,6,7,8,9],helper:8,almost:[5,4],incom:7,revis:8,parti:6,began:9,member:[8,9,5],python:[0,1,2,3,4,5,7,8,9],denot:5,iou:9,upon:[0,8,2,6,4],effect:[0,6,2,3],distutil:8,markupsaf:[2,7],off:[0,6,2,3,4],mention:7,well:[0,2,3,4,5,6,7,8,9],exampl:[0,2,4,5,6,3,8,9],command:8,choos:7,undefin:[0,8,9,5],usual:[8,6,2,9,5],module_writ:8,less:[9,7,4],heavili:7,web:8,point:[0,7,4,5,6,3,8],add:[0,8,2,4],lookup:[8,6,9,7],dest:8,arguabl:7,cache_impl:[8,6],five:[6,5],know:[7,4],xe2:7,mkstemp:8,insert:4,like:[0,2,3,4,5,6,7,8,9],success:8,page:[0,1,2,4,5,6,3,8,9],unreach:0,exceed:9,revers:8,captur:[8,2,3,9],pariti:9,"export":[0,5,4],smoothli:4,proper:8,librari:[0,8,2,6,7],tmp:[8,2],lead:[2,3,9],usag:[0,1,2,3,4,6,7,8,9],nutshel:4,although:5,stage:8,beaker:[8,6],about:[8,1,5,9,4],actual:[0,2,4,5,6,3,8,9],column:0,htmlentitydef:2,discard:2,x99a:7,disabl:[1,2,6,7,8,9],own:[0,2,3,4,5,6,7,8,9],populate_self:3,automat:[0,2,4,5,6,8,9],"dr\u00f4le":7,leverag:5,quote_plu:2,inner:0,arg1:3,arg2:3,"function":[0,2,3,4,5,6,7,8,9],keyerror:9,invalidate_def:6,eas:[2,9],inlin:[5,9,4],buf:[8,2],wherev:7,count:[0,8,9],made:[6,9],whether:[2,9,5],wish:[6,2,9],displai:8,record:[8,3,5],below:[0,7,4],otherwis:[8,9,7,5],evalu:[0,3,5],"int":9,dure:[8,4],filenam:[8,6,3],twist:0,pit:9,probabl:[0,8,9,6],mutual:8,percent:5,detail:[0,4,5,7,8,9],other:[0,2,3,4,5,6,7,8,9],bool:9,futur:[3,5],varieti:[6,5],post_pros:0,supports_cal:3,templateuri:3,some_condit:0,stai:[6,9],experienc:9,strict_undefin:[8,9],rule:[0,7,4],portion:0},objtypes:{"0":"py:attribute","1":"py:method","2":"py:class","3":"py:function"},titles:["Defs and Blocks","Table of Contents","Filtering and Buffering","Namespaces","Inheritance","Syntax","Caching","The Unicode Chapter","Usage","The Mako Runtime Environment"],objnames:{"0":["py","attribute","Python attribute"],"1":["py","method","Python method"],"2":["py","class","Python class"],"3":["py","function","Python function"]},filenames:["defs","index","filtering","namespaces","inheritance","syntax","caching","unicode","usage","runtime"]}) \ No newline at end of file diff --git a/lib/mako-0.7.2/doc/syntax.html b/lib/mako-0.7.2/doc/syntax.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/syntax.html @@ -0,0 +1,594 @@ + + + + + + + Syntax + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Syntax + + +

      + + Syntax + +

      +
      + +
      + +
      + + + +
      + +
      +

      Syntax?

      +

      A Mako template is parsed from a text stream containing any kind +of content, XML, HTML, email text, etc. The template can further +contain Mako-specific directives which represent variable and/or +expression substitutions, control structures (i.e. conditionals +and loops), server-side comments, full blocks of Python code, as +well as various tags that offer additional functionality. All of +these constructs compile into real Python code. This means that +you can leverage the full power of Python in almost every aspect +of a Mako template.

      +
      +

      Expression Substitution?

      +

      The simplest expression is just a variable substitution. The +syntax for this is the ${} construct, which is inspired by +Perl, Genshi, JSP EL, and others:

      +
      this is x: ${x}
      +
      +
      +

      Above, the string representation of x is applied to the +template’s output stream. If you’re wondering where x comes +from, it’s usually from the Context supplied to the +template’s rendering function. If x was not supplied to the +template and was not otherwise assigned locally, it evaluates to +a special value UNDEFINED. More on that later.

      +

      The contents within the ${} tag are evaluated by Python +directly, so full expressions are OK:

      +
      pythagorean theorem:  ${pow(x,2) + pow(y,2)}
      +
      +
      +

      The results of the expression are evaluated into a string result +in all cases before being rendered to the output stream, such as +the above example where the expression produces a numeric +result.

      +
      +
      +

      Expression Escaping?

      +

      Mako includes a number of built-in escaping mechanisms, +including HTML, URI and XML escaping, as well as a “trim” +function. These escapes can be added to an expression +substitution using the | operator:

      +
      ${"this is some text" | u}
      +
      +
      +

      The above expression applies URL escaping to the expression, and +produces this+is+some+text. The u name indicates URL +escaping, whereas h represents HTML escaping, x +represents XML escaping, and trim applies a trim function.

      +

      Read more about built-in filtering functions, including how to +make your own filter functions, in Filtering and Buffering.

      +
      +
      +

      Control Structures?

      +

      A control structure refers to all those things that control the +flow of a program – conditionals (i.e. if/else), loops (like +while and for), as well as things like try/except. In Mako, +control structures are written using the % marker followed +by a regular Python control expression, and are “closed” by +using another % marker with the tag “end<name>”, where +“<name>” is the keyword of the expression:

      +
      % if x==5:
      +    this is some output
      +% endif
      +
      +
      +

      The % can appear anywhere on the line as long as no text +precedes it; indentation is not significant. The full range of +Python “colon” expressions are allowed here, including +if/elif/else, while, for, and even def, although +Mako has a built-in tag for defs which is more full-featured.

      +
      % for a in ['one', 'two', 'three', 'four', 'five']:
      +    % if a[0] == 't':
      +    its two or three
      +    % elif a[0] == 'f':
      +    four/five
      +    % else:
      +    one
      +    % endif
      +% endfor
      +
      +
      +

      The % sign can also be “escaped”, if you actually want to +emit a percent sign as the first non whitespace character on a +line, by escaping it as in %%:

      +
      %% some text
      +
      +    %% some more text
      +
      +
      +
      +

      The Loop Context?

      +

      The loop context provides additional information about a loop +while inside of a % for structure:

      +
      <ul>
      +% for a in ("one", "two", "three"):
      +    <li>Item ${loop.index}: ${a}</li>
      +% endfor
      +</ul>
      +
      +
      +

      See The Loop Context for more information on this feature.

      +

      +New in version 0.7.

      +
      +
      +
      +

      Comments?

      +

      Comments come in two varieties. The single line comment uses +## as the first non-space characters on a line:

      +
      ## this is a comment.
      +...text ...
      +
      +
      +

      A multiline version exists using <%doc> ...text... </%doc>:

      +
      <%doc>
      +    these are comments
      +    more comments
      +</%doc>
      +
      +
      +
      +
      +

      Newline Filters?

      +

      The backslash (“\”) character, placed at the end of any +line, will consume the newline character before continuing to +the next line:

      +
      here is a line that goes onto \
      +another line.
      +
      +
      +

      The above text evaluates to:

      +
      here is a line that goes onto another line.
      +
      +
      +
      +
      +

      Python Blocks?

      +

      Any arbitrary block of python can be dropped in using the <% +%> tags:

      +
      this is a template
      +<%
      +    x = db.get_resource('foo')
      +    y = [z.element for z in x if x.frobnizzle==5]
      +%>
      +% for elem in y:
      +    element: ${elem}
      +% endfor
      +
      +
      +

      Within <% %>, you’re writing a regular block of Python code. +While the code can appear with an arbitrary level of preceding +whitespace, it has to be consistently formatted with itself. +Mako’s compiler will adjust the block of Python to be consistent +with the surrounding generated Python code.

      +
      +
      +

      Module-level Blocks?

      +

      A variant on <% %> is the module-level code block, denoted +by <%! %>. Code within these tags is executed at the module +level of the template, and not within the rendering function of +the template. Therefore, this code does not have access to the +template’s context and is only executed when the template is +loaded into memory (which can be only once per application, or +more, depending on the runtime environment). Use the <%! %> +tags to declare your template’s imports, as well as any +pure-Python functions you might want to declare:

      +
      <%!
      +    import mylib
      +    import re
      +
      +    def filter(text):
      +        return re.sub(r'^@', '', text)
      +%>
      +
      +
      +

      Any number of <%! %> blocks can be declared anywhere in a +template; they will be rendered in the resulting module +in a single contiguous block above all render callables, +in the order in which they appear in the source template.

      +
      +
      +

      Tags?

      +

      The rest of what Mako offers takes place in the form of tags. +All tags use the same syntax, which is similar to an XML tag +except that the first character of the tag name is a % +character. The tag is closed either by a contained slash +character, or an explicit closing tag:

      +
      <%include file="foo.txt"/>
      +
      +<%def name="foo" buffered="True">
      +    this is a def
      +</%def>
      +
      +
      +

      All tags have a set of attributes which are defined for each +tag. Some of these attributes are required. Also, many +attributes support evaluation, meaning you can embed an +expression (using ${}) inside the attribute text:

      +
      <%include file="/foo/bar/${myfile}.txt"/>
      +
      +
      +

      Whether or not an attribute accepts runtime evaluation depends +on the type of tag and how that tag is compiled into the +template. The best way to find out if you can stick an +expression in is to try it! The lexer will tell you if it’s not +valid.

      +

      Heres a quick summary of all the tags:

      +
      +

      <%page>?

      +

      This tag defines general characteristics of the template, +including caching arguments, and optional lists of arguments +which the template expects when invoked.

      +
      <%page args="x, y, z='default'"/>
      +
      +
      +

      Or a page tag that defines caching characteristics:

      +
      <%page cached="True" cache_type="memory"/>
      +
      +
      +

      Currently, only one <%page> tag gets used per template, the +rest get ignored. While this will be improved in a future +release, for now make sure you have only one <%page> tag +defined in your template, else you may not get the results you +want. The details of what <%page> is used for are described +further in The body() Method as well as Caching.

      +
      +
      +

      <%include>?

      +

      A tag that is familiar from other template languages, %include +is a regular joe that just accepts a file argument and calls in +the rendered result of that file:

      +
      <%include file="header.html"/>
      +
      +    hello world
      +
      +<%include file="footer.html"/>
      +
      +
      +

      Include also accepts arguments which are available as <%page> arguments in the receiving template:

      +
      <%include file="toolbar.html" args="current_section='members', username='ed'"/>
      +
      +
      +
      +
      +

      <%def>?

      +

      The %def tag defines a Python function which contains a set +of content, that can be called at some other point in the +template. The basic idea is simple:

      +
      <%def name="myfunc(x)">
      +    this is myfunc, x is ${x}
      +</%def>
      +
      +${myfunc(7)}
      +
      +
      +

      The %def tag is a lot more powerful than a plain Python def, as +the Mako compiler provides many extra services with %def that +you wouldn’t normally have, such as the ability to export defs +as template “methods”, automatic propagation of the current +Context, buffering/filtering/caching flags, and def calls +with content, which enable packages of defs to be sent as +arguments to other def calls (not as hard as it sounds). Get the +full deal on what %def can do in Defs and Blocks.

      +
      +
      +

      <%block>?

      +

      %block is a tag that is close to a %def, +except executes itself immediately in its base-most scope, +and can also be anonymous (i.e. with no name):

      +
      <%block filter="h">
      +    some <html> stuff.
      +</%block>
      +
      +
      +

      Inspired by Jinja2 blocks, named blocks offer a syntactically pleasing way +to do inheritance:

      +
      <html>
      +    <body>
      +    <%block name="header">
      +        <h2><%block name="title"/></h2>
      +    </%block>
      +    ${self.body()}
      +    </body>
      +</html>
      +
      +
      +

      Blocks are introduced in Using Blocks and further described in Inheritance.

      +

      +New in version 0.4.1.

      +
      +
      +

      <%namespace>?

      +

      %namespace is Mako’s equivalent of Python’s import +statement. It allows access to all the rendering functions and +metadata of other template files, plain Python modules, as well +as locally defined “packages” of functions.

      +
      <%namespace file="functions.html" import="*"/>
      +
      +
      +

      The underlying object generated by %namespace, an instance of +mako.runtime.Namespace, is a central construct used in +templates to reference template-specific information such as the +current URI, inheritance structures, and other things that are +not as hard as they sound right here. Namespaces are described +in Namespaces.

      +
      +
      +

      <%inherit>?

      +

      Inherit allows templates to arrange themselves in inheritance +chains. This is a concept familiar in many other template +languages.

      +
      <%inherit file="base.html"/>
      +
      +
      +

      When using the %inherit tag, control is passed to the topmost +inherited template first, which then decides how to handle +calling areas of content from its inheriting templates. Mako +offers a lot of flexibility in this area, including dynamic +inheritance, content wrapping, and polymorphic method calls. +Check it out in Inheritance.

      +
      +
      +

      <%nsname:defname>?

      +

      Any user-defined “tag” can be created against +a namespace by using a tag with a name of the form +<%<namespacename>:<defname>>. The closed and open formats of such a +tag are equivalent to an inline expression and the <%call> +tag, respectively.

      +
      <%mynamespace:somedef param="some value">
      +    this is the body
      +</%mynamespace:somedef>
      +
      +
      +

      To create custom tags which accept a body, see +Calling a Def with Embedded Content and/or Other Defs.

      +

      +New in version 0.2.3.

      +
      +
      +

      <%call>?

      +

      The call tag is the “classic” form of a user-defined tag, and is +roughly equivalent to the <%namespacename:defname> syntax +described above. This tag is also described in Calling a Def with Embedded Content and/or Other Defs.

      +
      +
      +

      <%doc>?

      +

      The %doc tag handles multiline comments:

      +
      <%doc>
      +    these are comments
      +    more comments
      +</%doc>
      +
      +
      +

      Also the ## symbol as the first non-space characters on a line can be used for single line comments.

      +
      +
      +

      <%text>?

      +

      This tag suspends the Mako lexer’s normal parsing of Mako +template directives, and returns its entire body contents as +plain text. It is used pretty much to write documentation about +Mako:

      +
      <%text filter="h">
      +    heres some fake mako ${syntax}
      +    <%def name="x()">${x}</%def>
      +</%text>
      +
      +
      +
      +
      +
      +

      Returning Early from a Template?

      +

      Sometimes you want to stop processing a template or <%def> +method in the middle and just use the text you’ve accumulated so +far. You can use a return statement inside a Python +block to do that.

      +
      % if not len(records):
      +    No records found.
      +    <% return %>
      +% endif
      +
      +
      +

      Or perhaps:

      +
      <%
      +    if not len(records):
      +        return
      +%>
      +
      +
      +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/unicode.html b/lib/mako-0.7.2/doc/unicode.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/unicode.html @@ -0,0 +1,474 @@ + + + + + + + The Unicode Chapter + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + The Unicode Chapter + + +

      + + The Unicode Chapter + +

      +
      + +
      + +
      + + + +
      + +
      +

      The Unicode Chapter?

      +

      The Python language supports two ways of representing what we +know as “strings”, i.e. series of characters. In Python 2, the +two types are string and unicode, and in Python 3 they are +bytes and string. A key aspect of the Python 2 string and +Python 3 bytes types are that they contain no information +regarding what encoding the data is stored in. For this +reason they were commonly referred to as byte strings on +Python 2, and Python 3 makes this name more explicit. The +origins of this come from Python’s background of being developed +before the Unicode standard was even available, back when +strings were C-style strings and were just that, a series of +bytes. Strings that had only values below 128 just happened to +be ASCII strings and were printable on the console, whereas +strings with values above 128 would produce all kinds of +graphical characters and bells.

      +

      Contrast the “byte-string” type with the “unicode/string” type. +Objects of this latter type are created whenever you say something like +u"hello world" (or in Python 3, just "hello world"). In this +case, Python represents each character in the string internally +using multiple bytes per character (something similar to +UTF-16). What’s important is that when using the +unicode/string type to store strings, Python knows the +data’s encoding; it’s in its own internal format. Whereas when +using the string/bytes type, it does not.

      +

      When Python 2 attempts to treat a byte-string as a string, which +means it’s attempting to compare/parse its characters, to coerce +it into another encoding, or to decode it to a unicode object, +it has to guess what the encoding is. In this case, it will +pretty much always guess the encoding as ascii... and if the +byte-string contains bytes above value 128, you’ll get an error. +Python 3 eliminates much of this confusion by just raising an +error unconditionally if a byte-string is used in a +character-aware context.

      +

      There is one operation that Python can do with a non-ASCII +byte-string, and it’s a great source of confusion: it can dump the +byte-string straight out to a stream or a file, with nary a care +what the encoding is. To Python, this is pretty much like +dumping any other kind of binary data (like an image) to a +stream somewhere. In Python 2, it is common to see programs that +embed all kinds of international characters and encodings into +plain byte-strings (i.e. using "hello world" style literals) +can fly right through their run, sending reams of strings out to +wherever they are going, and the programmer, seeing the same +output as was expressed in the input, is now under the illusion +that his or her program is Unicode-compliant. In fact, their +program has no unicode awareness whatsoever, and similarly has +no ability to interact with libraries that are unicode aware. +Python 3 makes this much less likely by defaulting to unicode as +the storage format for strings.

      +

      The “pass through encoded data” scheme is what template +languages like Cheetah and earlier versions of Myghty do by +default. Mako as of version 0.2 also supports this mode of +operation when using Python 2, using the disable_unicode=True +flag. However, when using Mako in its default mode of +unicode-aware, it requires explicitness when dealing with +non-ASCII encodings. Additionally, if you ever need to handle +unicode strings and other kinds of encoding conversions more +intelligently, the usage of raw byte-strings quickly becomes a +nightmare, since you are sending the Python interpreter +collections of bytes for which it can make no intelligent +decisions with regards to encoding. In Python 3 Mako only allows +usage of native, unicode strings.

      +

      In normal Mako operation, all parsed template constructs and +output streams are handled internally as Python unicode +objects. It’s only at the point of render() that this unicode +stream may be rendered into whatever the desired output encoding +is. The implication here is that the template developer must +:ensure that the encoding of all non-ASCII templates is explicit (still required in Python 3), +that all non-ASCII-encoded expressions are in one way or another +converted to unicode +(not much of a burden in Python 3), and that the output stream of the +template is handled as a unicode stream being encoded to some +encoding (still required in Python 3).

      +
      +

      Specifying the Encoding of a Template File?

      +

      This is the most basic encoding-related setting, and it is +equivalent to Python’s “magic encoding comment”, as described in +pep-0263. Any +template that contains non-ASCII characters requires that this +comment be present so that Mako can decode to unicode (and also +make usage of Python’s AST parsing services). Mako’s lexer will +use this encoding in order to convert the template source into a +unicode object before continuing its parsing:

      +
      ## -*- coding: utf-8 -*-
      +
      +Alors vous imaginez ma surprise, au lever du jour, quand
      +une dr?le de petite voix m?a r?veill?. Elle disait:
      + ? S?il vous pla?t? dessine-moi un mouton! ?
      +
      +
      +

      For the picky, the regular expression used is derived from that +of the above mentioned pep:

      +
      #.*coding[:=]\s*([-\w.]+).*\n
      +
      +
      +

      The lexer will convert to unicode in all cases, so that if any +characters exist in the template that are outside of the +specified encoding (or the default of ascii), the error will +be immediate.

      +

      As an alternative, the template encoding can be specified +programmatically to either Template or TemplateLookup via +the input_encoding parameter:

      +
      t = TemplateLookup(directories=['./'], input_encoding='utf-8')
      +
      +
      +

      The above will assume all located templates specify utf-8 +encoding, unless the template itself contains its own magic +encoding comment, which takes precedence.

      +
      +
      +

      Handling Expressions?

      +

      The next area that encoding comes into play is in expression +constructs. By default, Mako’s treatment of an expression like +this:

      +
      ${"hello world"}
      +
      +
      +

      looks something like this:

      +
      context.write(unicode("hello world"))
      +
      +
      +

      In Python 3, it’s just:

      +
      context.write(str("hello world"))
      +
      +
      +

      That is, the output of all expressions is run through the +``unicode`` built-in. This is the default setting, and can be +modified to expect various encodings. The unicode step serves +both the purpose of rendering non-string expressions into +strings (such as integers or objects which contain __str()__ +methods), and to ensure that the final output stream is +constructed as a unicode object. The main implication of this is +that any raw byte-strings that contain an encoding other than +ASCII must first be decoded to a Python unicode object. It +means you can’t say this in Python 2:

      +
      ${"voix m?a r?veill?."}  ## error in Python 2!
      +
      +
      +

      You must instead say this:

      +
      ${u"voix m?a r?veill?."}  ## OK !
      +
      +
      +

      Similarly, if you are reading data from a file that is streaming +bytes, or returning data from some object that is returning a +Python byte-string containing a non-ASCII encoding, you have to +explicitly decode to unicode first, such as:

      +
      ${call_my_object().decode('utf-8')}
      +
      +
      +

      Note that filehandles acquired by open() in Python 3 default +to returning “text”, that is the decoding is done for you. See +Python 3’s documentation for the open() built-in for details on +this.

      +

      If you want a certain encoding applied to all expressions, +override the unicode builtin with the decode built-in at the +Template or TemplateLookup level:

      +
      t = Template(templatetext, default_filters=['decode.utf8'])
      +
      +
      +

      Note that the built-in decode object is slower than the +unicode function, since unlike unicode it’s not a Python +built-in, and it also checks the type of the incoming data to +determine if string conversion is needed first.

      +

      The default_filters argument can be used to entirely customize +the filtering process of expressions. This argument is described +in The default_filters Argument.

      +
      +
      +

      Defining Output Encoding?

      +

      Now that we have a template which produces a pure unicode output +stream, all the hard work is done. We can take the output and do +anything with it.

      +

      As stated in the “Usage” chapter, both Template and +TemplateLookup accept output_encoding and encoding_errors +parameters which can be used to encode the output in any Python +supported codec:

      +
      from mako.template import Template
      +from mako.lookup import TemplateLookup
      +
      +mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')
      +
      +mytemplate = mylookup.get_template("foo.txt")
      +print mytemplate.render()
      +
      +
      +

      render() will return a bytes object in Python 3 if an output +encoding is specified. By default it performs no encoding and +returns a native string.

      +

      render_unicode() will return the template output as a Python +unicode object (or string in Python 3):

      +
      print mytemplate.render_unicode()
      +
      +
      +

      The above method disgards the output encoding keyword argument; +you can encode yourself by saying:

      +
      print mytemplate.render_unicode().encode('utf-8', 'replace')
      +
      +
      +
      +

      Buffer Selection?

      +

      Mako does play some games with the style of buffering used +internally, to maximize performance. Since the buffer is by far +the most heavily used object in a render operation, it’s +important!

      +

      When calling render() on a template that does not specify any +output encoding (i.e. it’s ascii), Python’s cStringIO module, +which cannot handle encoding of non-ASCII unicode objects +(even though it can send raw byte-strings through), is used for +buffering. Otherwise, a custom Mako class called +FastEncodingBuffer is used, which essentially is a super +dumbed-down version of StringIO that gathers all strings into +a list and uses u''.join(elements) to produce the final output +– it’s markedly faster than StringIO.

      +
      +
      +
      +

      Saying to Heck with It: Disabling the Usage of Unicode Entirely?

      +

      Some segments of Mako’s userbase choose to make no usage of +Unicode whatsoever, and instead would prefer the “pass through” +approach; all string expressions in their templates return +encoded byte-strings, and they would like these strings to pass +right through. The only advantage to this approach is that +templates need not use u"" for literal strings; there’s an +arguable speed improvement as well since raw byte-strings +generally perform slightly faster than unicode objects in +Python. For these users, assuming they’re sticking with Python +2, they can hit the disable_unicode=True flag as so:

      +
      # -*- encoding:utf-8 -*-
      +from mako.template import Template
      +
      +t = Template("dr?le de petite voix m?a r?veill?.", disable_unicode=True, input_encoding='utf-8')
      +print t.code
      +
      +
      +

      The disable_unicode mode is strictly a Python 2 thing. It is +not supported at all in Python 3.

      +

      The generated module source code will contain elements like +these:

      +
      # -*- encoding:utf-8 -*-
      +#  ...more generated code ...
      +
      +def render_body(context,**pageargs):
      +    context.caller_stack.push_frame()
      +    try:
      +        __M_locals = dict(pageargs=pageargs)
      +        # SOURCE LINE 1
      +        context.write('dr\xc3\xb4le de petite voix m\xe2\x80\x99a r\xc3\xa9veill\xc3\xa9.')
      +        return ''
      +    finally:
      +        context.caller_stack.pop_frame()
      +
      +
      +

      Where above that the string literal used within Context.write() +is a regular byte-string.

      +

      When disable_unicode=True is turned on, the default_filters +argument which normally defaults to ["unicode"] now defaults +to ["str"] instead. Setting default_filters to the empty list +[] can remove the overhead of the str call. Also, in this +mode you cannot safely call render_unicode() – you’ll get +unicode/decode errors.

      +

      The h filter (HTML escape) uses a less performant pure Python +escape function in non-unicode mode. This because +MarkupSafe only supports Python unicode objects for non-ASCII +strings.

      +

      +Changed in version 0.3.4: In prior versions, it used cgi.escape(), which has been replaced +with a function that also escapes single quotes.

      +
      +

      Rules for using disable_unicode=True?

      +
        +
      • Don’t use this mode unless you really, really want to and you +absolutely understand what you’re doing.
      • +
      • Don’t use this option just because you don’t want to learn to +use Unicode properly; we aren’t supporting user issues in this +mode of operation. We will however offer generous help for the +vast majority of users who stick to the Unicode program.
      • +
      • Python 3 is unicode by default, and the flag is not available +when running on Python 3.
      • +
      +
      +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/doc/usage.html b/lib/mako-0.7.2/doc/usage.html new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/doc/usage.html @@ -0,0 +1,1055 @@ + + + + + + + Usage + — + Mako 0.7.2 Documentation + + + + + + + + + + + + + + + + + + + + +
      +
      +
      + Hyperfast and lightweight templating for the Python platform. +
      + + +
      + + + +
      + + + + + + + + + + + +
      + + + +
      +

      Mako 0.7.2 Documentation

      + + + +
      + Release: 0.7.2 + +
      + +
      + +
      + + +
      + Mako 0.7.2 Documentation + ? + Usage + + +

      + + Usage + +

      +
      + +
      + +
      + + + +
      + +
      +

      Usage?

      +
      +

      Basic Usage?

      +

      This section describes the Python API for Mako templates. If you +are using Mako within a web framework such as Pylons, the work +of integrating Mako’s API is already done for you, in which case +you can skip to the next section, Syntax.

      +

      The most basic way to create a template and render it is through +the Template class:

      +
      from mako.template import Template
      +
      +mytemplate = Template("hello world!")
      +print mytemplate.render()
      +
      +
      +

      Above, the text argument to Template is compiled into a +Python module representation. This module contains a function +called render_body(), which produces the output of the +template. When mytemplate.render() is called, Mako sets up a +runtime environment for the template and calls the +render_body() function, capturing the output into a buffer and +returning its string contents.

      +

      The code inside the render_body() function has access to a +namespace of variables. You can specify these variables by +sending them as additional keyword arguments to the render() +method:

      +
      from mako.template import Template
      +
      +mytemplate = Template("hello, ${name}!")
      +print mytemplate.render(name="jack")
      +
      +
      +

      The render() method calls upon Mako to create a +Context object, which stores all the variable names accessible +to the template and also stores a buffer used to capture output. +You can create this Context yourself and have the template +render with it, using the render_context() method:

      +
      from mako.template import Template
      +from mako.runtime import Context
      +from StringIO import StringIO
      +
      +mytemplate = Template("hello, ${name}!")
      +buf = StringIO()
      +ctx = Context(buf, name="jack")
      +mytemplate.render_context(ctx)
      +print buf.getvalue()
      +
      +
      +
      +
      +

      Using File-Based Templates?

      +

      A Template can also load its template source code from a file, +using the filename keyword argument:

      +
      from mako.template import Template
      +
      +mytemplate = Template(filename='/docs/mytmpl.txt')
      +print mytemplate.render()
      +
      +
      +

      For improved performance, a Template which is loaded from a +file can also cache the source code to its generated module on +the filesystem as a regular Python module file (i.e. a .py +file). To do this, just add the module_directory argument to +the template:

      +
      from mako.template import Template
      +
      +mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules')
      +print mytemplate.render()
      +
      +
      +

      When the above code is rendered, a file +/tmp/mako_modules/docs/mytmpl.txt.py is created containing the +source code for the module. The next time a Template with the +same arguments is created, this module file will be +automatically re-used.

      +
      +
      +

      Using TemplateLookup?

      +

      All of the examples thus far have dealt with the usage of a +single Template object. If the code within those templates +tries to locate another template resource, it will need some way +to find them, using simple URI strings. For this need, the +resolution of other templates from within a template is +accomplished by the TemplateLookup class. This class is +constructed given a list of directories in which to search for +templates, as well as keyword arguments that will be passed to +the Template objects it creates:

      +
      from mako.template import Template
      +from mako.lookup import TemplateLookup
      +
      +mylookup = TemplateLookup(directories=['/docs'])
      +mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup)
      +
      +
      +

      Above, we created a textual template which includes the file +"header.txt". In order for it to have somewhere to look for +"header.txt", we passed a TemplateLookup object to it, which +will search in the directory /docs for the file "header.txt".

      +

      Usually, an application will store most or all of its templates +as text files on the filesystem. So far, all of our examples +have been a little bit contrived in order to illustrate the +basic concepts. But a real application would get most or all of +its templates directly from the TemplateLookup, using the +aptly named get_template() method, which accepts the URI of the +desired template:

      +
      from mako.template import Template
      +from mako.lookup import TemplateLookup
      +
      +mylookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules')
      +
      +def serve_template(templatename, **kwargs):
      +    mytemplate = mylookup.get_template(templatename)
      +    print mytemplate.render(**kwargs)
      +
      +
      +

      In the example above, we create a TemplateLookup which will +look for templates in the /docs directory, and will store +generated module files in the /tmp/mako_modules directory. The +lookup locates templates by appending the given URI to each of +its search directories; so if you gave it a URI of +/etc/beans/info.txt, it would search for the file +/docs/etc/beans/info.txt, else raise a TopLevelNotFound +exception, which is a custom Mako exception.

      +

      When the lookup locates templates, it will also assign a uri +property to the Template which is the URI passed to the +get_template() call. Template uses this URI to calculate the +name of its module file. So in the above example, a +templatename argument of /etc/beans/info.txt will create a +module file /tmp/mako_modules/etc/beans/info.txt.py.

      +
      +

      Setting the Collection Size?

      +

      The TemplateLookup also serves the important need of caching a +fixed set of templates in memory at a given time, so that +successive URI lookups do not result in full template +compilations and/or module reloads on each request. By default, +the TemplateLookup size is unbounded. You can specify a fixed +size using the collection_size argument:

      +
      mylookup = TemplateLookup(directories=['/docs'],
      +                module_directory='/tmp/mako_modules', collection_size=500)
      +
      +
      +

      The above lookup will continue to load templates into memory +until it reaches a count of around 500. At that point, it will +clean out a certain percentage of templates using a least +recently used scheme.

      +
      +
      +

      Setting Filesystem Checks?

      +

      Another important flag on TemplateLookup is +filesystem_checks. This defaults to True, and says that each +time a template is returned by the get_template() method, the +revision time of the original template file is checked against +the last time the template was loaded, and if the file is newer +will reload its contents and recompile the template. On a +production system, setting filesystem_checks to False can +afford a small to moderate performance increase (depending on +the type of filesystem used).

      +
      +
      +
      +

      Using Unicode and Encoding?

      +

      Both Template and TemplateLookup accept output_encoding +and encoding_errors parameters which can be used to encode the +output in any Python supported codec:

      +
      from mako.template import Template
      +from mako.lookup import TemplateLookup
      +
      +mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')
      +
      +mytemplate = mylookup.get_template("foo.txt")
      +print mytemplate.render()
      +
      +
      +

      When using Python 3, the render() method will return a bytes +object, if output_encoding is set. Otherwise it returns a +string.

      +

      Additionally, the render_unicode() method exists which will +return the template output as a Python unicode object, or in +Python 3 a string:

      +
      print mytemplate.render_unicode()
      +
      +
      +

      The above method disregards the output encoding keyword +argument; you can encode yourself by saying:

      +
      print mytemplate.render_unicode().encode('utf-8', 'replace')
      +
      +
      +

      Note that Mako’s ability to return data in any encoding and/or +unicode implies that the underlying output stream of the +template is a Python unicode object. This behavior is described +fully in The Unicode Chapter.

      +
      +
      +

      Handling Exceptions?

      +

      Template exceptions can occur in two distinct places. One is +when you lookup, parse and compile the template, the other +is when you run the template. Within the running of a +template, exceptions are thrown normally from whatever Python +code originated the issue. Mako has its own set of exception +classes which mostly apply to the lookup and lexer/compiler +stages of template construction. Mako provides some library +routines that can be used to help provide Mako-specific +information about any exception’s stack trace, as well as +formatting the exception within textual or HTML format. In all +cases, the main value of these handlers is that of converting +Python filenames, line numbers, and code samples into Mako +template filenames, line numbers, and code samples. All lines +within a stack trace which correspond to a Mako template module +will be converted to be against the originating template file.

      +

      To format exception traces, the text_error_template() and +html_error_template() functions are provided. They make usage of +sys.exc_info() to get at the most recently thrown exception. +Usage of these handlers usually looks like:

      +
      from mako import exceptions
      +
      +try:
      +    template = lookup.get_template(uri)
      +    print template.render()
      +except:
      +    print exceptions.text_error_template().render()
      +
      +
      +

      Or for the HTML render function:

      +
      from mako import exceptions
      +
      +try:
      +    template = lookup.get_template(uri)
      +    print template.render()
      +except:
      +    print exceptions.html_error_template().render()
      +
      +
      +

      The html_error_template() template accepts two options: +specifying full=False causes only a section of an HTML +document to be rendered. Specifying css=False will disable the +default stylesheet from being rendered.

      +

      E.g.:

      +
      print exceptions.html_error_template().render(full=False)
      +
      +
      +

      The HTML render function is also available built-in to +Template using the format_exceptions flag. In this case, any +exceptions raised within the render stage of the template +will result in the output being substituted with the output of +html_error_template():

      +
      template = Template(filename="/foo/bar", format_exceptions=True)
      +print template.render()
      +
      +
      +

      Note that the compile stage of the above template occurs when +you construct the Template itself, and no output stream is +defined. Therefore exceptions which occur within the +lookup/parse/compile stage will not be handled and will +propagate normally. While the pre-render traceback usually will +not include any Mako-specific lines anyway, it will mean that +exceptions which occur previous to rendering and those which +occur within rendering will be handled differently... so the +try/except patterns described previously are probably of more +general use.

      +

      The underlying object used by the error template functions is +the RichTraceback object. This object can also be used +directly to provide custom error views. Here’s an example usage +which describes its general API:

      +
      from mako.exceptions import RichTraceback
      +
      +try:
      +    template = lookup.get_template(uri)
      +    print template.render()
      +except:
      +    traceback = RichTraceback()
      +    for (filename, lineno, function, line) in traceback.traceback:
      +        print "File %s, line %s, in %s" % (filename, lineno, function)
      +        print line, "\n"
      +    print "%s: %s" % (str(traceback.error.__class__.__name__), traceback.error)
      +
      +
      +
      +
      +

      Common Framework Integrations?

      +

      The Mako distribution includes a little bit of helper code for +the purpose of using Mako in some popular web framework +scenarios. This is a brief description of what’s included.

      +
      +

      WSGI?

      +

      A sample WSGI application is included in the distribution in the +file examples/wsgi/run_wsgi.py. This runner is set up to pull +files from a templates as well as an htdocs directory and +includes a rudimental two-file layout. The WSGI runner acts as a +fully functional standalone web server, using wsgiutils to run +itself, and propagates GET and POST arguments from the request +into the Context, can serve images, CSS files and other kinds +of files, and also displays errors using Mako’s included +exception-handling utilities.

      +
      +
      +

      Pygments?

      +

      A Pygments-compatible syntax +highlighting module is included under mako.ext.pygmentplugin. +This module is used in the generation of Mako documentation and +also contains various setuptools entry points under the heading +pygments.lexers, including mako, html+mako, xml+mako +(see the setup.py file for all the entry points).

      +
      +
      +

      Babel?

      +

      Mako provides support for extracting gettext messages from +templates via a Babel extractor +entry point under mako.ext.babelplugin.

      +

      Gettext messages are extracted from all Python code sections, +including those of control lines and expressions embedded +in tags.

      +

      Translator +comments +may also be extracted from Mako templates when a comment tag is +specified to Babel (such as with +the -c option).

      +

      For example, a project "myproj" contains the following Mako +template at myproj/myproj/templates/name.html:

      +
      <div id="name">
      +  Name:
      +  ## TRANSLATORS: This is a proper name. See the gettext
      +  ## manual, section Names.
      +  ${_('Francois Pinard')}
      +</div>
      +
      +
      +

      To extract gettext messages from this template the project needs +a Mako section in its Babel Extraction Method Mapping +file +(typically located at myproj/babel.cfg):

      +
      # Extraction from Python source files
      +
      +[python: myproj/**.py]
      +
      +# Extraction from Mako templates
      +
      +[mako: myproj/templates/**.html]
      +input_encoding = utf-8
      +
      +
      +

      The Mako extractor supports an optional input_encoding +parameter specifying the encoding of the templates (identical to +Template/TemplateLookup‘s input_encoding parameter).

      +

      Invoking Babel‘s extractor at the +command line in the project’s root directory:

      +
      myproj$ pybabel extract -F babel.cfg -c "TRANSLATORS:" .
      +
      +
      +

      will output a gettext catalog to stdout including the following:

      +
      #. TRANSLATORS: This is a proper name. See the gettext
      +#. manual, section Names.
      +#: myproj/templates/name.html:5
      +msgid "Francois Pinard"
      +msgstr ""
      +
      +
      +

      This is only a basic example: +Babel can be invoked from setup.py +and its command line options specified in the accompanying +setup.cfg via Babel Distutils/Setuptools +Integration.

      +

      Comments must immediately precede a gettext message to be +extracted. In the following case the TRANSLATORS: comment would +not have been extracted:

      +
      <div id="name">
      +  ## TRANSLATORS: This is a proper name. See the gettext
      +  ## manual, section Names.
      +  Name: ${_('Francois Pinard')}
      +</div>
      +
      +
      +

      See the Babel User +Guide +for more information.

      +
      +
      +
      +

      API Reference?

      +
      +
      +class mako.template.Template(text=None, filename=None, uri=None, format_exceptions=False, error_handler=None, lookup=None, output_encoding=None, encoding_errors='strict', module_directory=None, cache_args=None, cache_impl='beaker', cache_enabled=True, cache_type=None, cache_dir=None, cache_url=None, module_filename=None, input_encoding=None, disable_unicode=False, module_writer=None, bytestring_passthrough=False, default_filters=None, buffer_filters=(), strict_undefined=False, imports=None, enable_loop=True, preprocessor=None)?
      +

      Bases: object

      +

      Represents a compiled template.

      +

      Template includes a reference to the original +template source (via the source attribute) +as well as the source code of the +generated Python module (i.e. the code attribute), +as well as a reference to an actual Python module.

      +

      Template is constructed using either a literal string +representing the template text, or a filename representing a filesystem +path to a source file.

      + +++ + + + +
      Parameters:
        +
      • text – textual template source. This argument is mutually +exclusive versus the filename parameter.
      • +
      • filename – filename of the source template. This argument is +mutually exclusive versus the text parameter.
      • +
      • buffer_filters – string list of filters to be applied +to the output of %defs which are buffered, cached, or otherwise +filtered, after all filters +defined with the %def itself have been applied. Allows the +creation of default expression filters that let the output +of return-valued %defs “opt out” of that filtering via +passing special attributes or objects.
      • +
      • bytestring_passthrough

        When True, and output_encoding is +set to None, and Template.render() is used to render, +the StringIO or cStringIO buffer will be used instead of the +default “fast” buffer. This allows raw bytestrings in the +output stream, such as in expressions, to pass straight +through to the buffer. This flag is forced +to True if disable_unicode is also configured.

        +

        +New in version 0.4: Added to provide the same behavior as that of the previous series.

        +
      • +
      • cache_args – Dictionary of cache configuration arguments that +will be passed to the CacheImpl. See Caching.
      • +
      • cache_dir

        +Deprecated since version 0.6: Use the 'dir' argument in the cache_args dictionary. +See Caching.

        +
      • +
      • cache_enabled – Boolean flag which enables caching of this +template. See Caching.
      • +
      • cache_impl – String name of a CacheImpl caching +implementation to use. Defaults to 'beaker'.
      • +
      • cache_type

        +Deprecated since version 0.6: Use the 'type' argument in the cache_args dictionary. +See Caching.

        +
      • +
      • cache_url

        +Deprecated since version 0.6: Use the 'url' argument in the cache_args dictionary. +See Caching.

        +
      • +
      • default_filters – List of string filter names that will +be applied to all expressions. See The default_filters Argument.
      • +
      • disable_unicode – Disables all awareness of Python Unicode +objects. See Saying to Heck with It: Disabling the Usage of Unicode Entirely.
      • +
      • enable_loop – When True, enable the loop context variable. +This can be set to False to support templates that may +be making usage of the name “loop”. Individual templates can +re-enable the “loop” context by placing the directive +enable_loop="True" inside the <%page> tag – see +Migrating Legacy Templates that Use the Word “loop”.
      • +
      • encoding_errors – Error parameter passed to encode() when +string encoding is performed. See Using Unicode and Encoding.
      • +
      • error_handler – Python callable which is called whenever +compile or runtime exceptions occur. The callable is passed +the current context as well as the exception. If the +callable returns True, the exception is considered to +be handled, else it is re-raised after the function +completes. Is used to provide custom error-rendering +functions.
      • +
      • format_exceptions – if True, exceptions which occur during +the render phase of this template will be caught and +formatted into an HTML error page, which then becomes the +rendered result of the render() call. Otherwise, +runtime exceptions are propagated outwards.
      • +
      • imports – String list of Python statements, typically individual +“import” lines, which will be placed into the module level +preamble of all generated Python modules. See the example +in The default_filters Argument.
      • +
      • input_encoding – Encoding of the template’s source code. Can +be used in lieu of the coding comment. See +Using Unicode and Encoding as well as The Unicode Chapter for +details on source encoding.
      • +
      • lookup – a TemplateLookup instance that will be used +for all file lookups via the <%namespace>, +<%include>, and <%inherit> tags. See +Using TemplateLookup.
      • +
      • module_directory – Filesystem location where generated +Python module files will be placed.
      • +
      • module_filename – Overrides the filename of the generated +Python module file. For advanced usage only.
      • +
      • module_writer

        A callable which overrides how the Python +module is written entirely. The callable is passed the +encoded source content of the module and the destination +path to be written to. The default behavior of module writing +uses a tempfile in conjunction with a file move in order +to make the operation atomic. So a user-defined module +writing function that mimics the default behavior would be:

        +
        import tempfile
        +import os
        +import shutil
        +
        +def module_writer(source, outputpath):
        +    (dest, name) = \
        +        tempfile.mkstemp(
        +            dir=os.path.dirname(outputpath)
        +        )
        +
        +    os.write(dest, source)
        +    os.close(dest)
        +    shutil.move(name, outputpath)
        +
        +from mako.template import Template
        +mytemplate = Template(
        +                file="index.html",
        +                module_directory="/path/to/modules",
        +                module_writer=module_writer
        +            )
        +
        +
        +

        The function is provided for unusual configurations where +certain platform-specific permissions or other special +steps are needed.

        +
      • +
      • output_encoding – The encoding to use when render() +is called. +See Using Unicode and Encoding as well as The Unicode Chapter.
      • +
      • preprocessor – Python callable which will be passed +the full template source before it is parsed. The return +result of the callable will be used as the template source +code.
      • +
      • strict_undefined

        Replaces the automatic usage of +UNDEFINED for any undeclared variables not located in +the Context with an immediate raise of +NameError. The advantage is immediate reporting of +missing variables which include the name.

        +

        +New in version 0.3.6.

        +
      • +
      • uri – string URI or other identifier for this template. +If not provided, the uri is generated from the filesystem +path, or from the in-memory identity of a non-file-based +template. The primary usage of the uri is to provide a key +within TemplateLookup, as well as to generate the +file path of the generated Python module file, if +module_directory is specified.
      • +
      +
      +
      +
      +code?
      +

      Return the module source code for this Template.

      +
      + +
      +
      +get_def(name)?
      +

      Return a def of this template as a DefTemplate.

      +
      + +
      +
      +render(*args, **data)?
      +

      Render the output of this template as a string.

      +

      If the template specifies an output encoding, the string +will be encoded accordingly, else the output is raw (raw +output uses cStringIO and can’t handle multibyte +characters). A Context object is created corresponding +to the given data. Arguments that are explicitly declared +by this template’s internal rendering method are also +pulled from the given *args, **data members.

      +
      + +
      +
      +render_context(context, *args, **kwargs)?
      +

      Render this Template with the given context.

      +

      The data is written to the context’s buffer.

      +
      + +
      +
      +render_unicode(*args, **data)?
      +

      Render the output of this template as a unicode object.

      +
      + +
      +
      +source?
      +

      Return the template source code for this Template.

      +
      + +
      + +
      +
      +class mako.template.DefTemplate(parent, callable_)?
      +

      Bases: mako.template.Template

      +

      A Template which represents a callable def in a parent +template.

      +
      + +
      +
      +class mako.lookup.TemplateCollection?
      +

      Bases: object

      +

      Represent a collection of Template objects, +identifiable via URI.

      +

      A TemplateCollection is linked to the usage of +all template tags that address other templates, such +as <%include>, <%namespace>, and <%inherit>. +The file attribute of each of those tags refers +to a string URI that is passed to that Template +object’s TemplateCollection for resolution.

      +

      TemplateCollection is an abstract class, +with the usual default implementation being TemplateLookup.

      +
      +
      +adjust_uri(uri, filename)?
      +

      Adjust the given uri based on the calling filename.

      +

      When this method is called from the runtime, the +filename parameter is taken directly to the filename +attribute of the calling template. Therefore a custom +TemplateCollection subclass can place any string +identifier desired in the filename parameter of the +Template objects it constructs and have them come back +here.

      +
      + +
      +
      +filename_to_uri(uri, filename)?
      +

      Convert the given filename to a URI relative to +this TemplateCollection.

      +
      + +
      +
      +get_template(uri, relativeto=None)?
      +

      Return a Template object corresponding to the given +uri.

      +

      The default implementation raises +NotImplementedError. Implementations should +raise TemplateLookupException if the given uri +cannot be resolved.

      + +++ + + + +
      Parameters:
        +
      • uri – String URI of the template to be resolved.
      • +
      • relativeto – if present, the given uri is assumed to +be relative to this URI.
      • +
      +
      +
      + +
      +
      +has_template(uri)?
      +

      Return True if this TemplateLookup is +capable of returning a Template object for the +given uri.

      + +++ + + + +
      Parameters:uri – String URI of the template to be resolved.
      +
      + +
      + +
      +
      +class mako.lookup.TemplateLookup(directories=None, module_directory=None, filesystem_checks=True, collection_size=-1, format_exceptions=False, error_handler=None, disable_unicode=False, bytestring_passthrough=False, output_encoding=None, encoding_errors='strict', cache_args=None, cache_impl='beaker', cache_enabled=True, cache_type=None, cache_dir=None, cache_url=None, modulename_callable=None, module_writer=None, default_filters=None, buffer_filters=(), strict_undefined=False, imports=None, enable_loop=True, input_encoding=None, preprocessor=None)?
      +

      Bases: mako.lookup.TemplateCollection

      +

      Represent a collection of templates that locates template source files +from the local filesystem.

      +

      The primary argument is the directories argument, the list of +directories to search:

      +
      lookup = TemplateLookup(["/path/to/templates"])
      +some_template = lookup.get_template("/index.html")
      +
      +
      +

      The TemplateLookup can also be given Template objects +programatically using put_string() or put_template():

      +
      lookup = TemplateLookup()
      +lookup.put_string("base.html", '''
      +    <html><body>${self.next()}</body></html>
      +''')
      +lookup.put_string("hello.html", '''
      +    <%include file='base.html'/>
      +
      +    Hello, world !
      +''')
      +
      +
      + +++ + + + +
      Parameters:
        +
      • directories – A list of directory names which will be +searched for a particular template URI. The URI is appended +to each directory and the filesystem checked.
      • +
      • collection_size – Approximate size of the collection used +to store templates. If left at its default of -1, the size +is unbounded, and a plain Python dictionary is used to +relate URI strings to Template instances. +Otherwise, a least-recently-used cache object is used which +will maintain the size of the collection approximately to +the number given.
      • +
      • filesystem_checks – When at its default value of True, +each call to TemplateLookup.get_template() will +compare the filesystem last modified time to the time in +which an existing Template object was created. +This allows the TemplateLookup to regenerate a +new Template whenever the original source has +been updated. Set this to False for a very minor +performance increase.
      • +
      • modulename_callable – A callable which, when present, +is passed the path of the source file as well as the +requested URI, and then returns the full path of the +generated Python module file. This is used to inject +alternate schemes for Python module location. If left at +its default of None, the built in system of generation +based on module_directory plus uri is used.
      • +
      +
      +

      All other keyword parameters available for +Template are mirrored here. When new +Template objects are created, the keywords +established with this TemplateLookup are passed on +to each new Template.

      +
      +
      +adjust_uri(uri, relativeto)?
      +

      Adjust the given uri based on the given relative URI.

      +
      + +
      +
      +filename_to_uri(filename)?
      +

      Convert the given filename to a URI relative to +this TemplateCollection.

      +
      + +
      +
      +get_template(uri)?
      +

      Return a Template object corresponding to the given +uri.

      +
      +

      Note

      +

      The relativeto argument is not supported here at the moment.

      +
      +
      + +
      +
      +put_string(uri, text)?
      +

      Place a new Template object into this +TemplateLookup, based on the given string of +text.

      +
      + +
      +
      +put_template(uri, template)?
      +

      Place a new Template object into this +TemplateLookup, based on the given +Template object.

      +
      + +
      + +
      +
      +class mako.exceptions.RichTraceback(error=None, traceback=None)?
      +

      Bases: object

      +

      Pull the current exception from the sys traceback and extracts +Mako-specific template information.

      +

      See the usage examples in Handling Exceptions.

      +
      +
      +error?
      +

      the exception instance.

      +
      + +
      +
      +message?
      +

      the exception error message as unicode.

      +
      + +
      +
      +source?
      +

      source code of the file where the error occurred. +If the error occurred within a compiled template, +this is the template source.

      +
      + +
      +
      +lineno?
      +

      line number where the error occurred. If the error +occurred within a compiled template, the line number +is adjusted to that of the template source.

      +
      + +
      +
      +records?
      +

      a list of 8-tuples containing the original +python traceback elements, plus the +filename, line number, source line, and full template source +for the traceline mapped back to its originating source +template, if any for that traceline (else the fields are None).

      +
      + +
      +
      +reverse_records?
      +

      the list of records in reverse +traceback – a list of 4-tuples, in the same format as a regular +python traceback, with template-corresponding +traceback records replacing the originals.

      +
      + +
      +
      +reverse_traceback?
      +

      the traceback list in reverse.

      +
      + +
      + +
      +
      +mako.exceptions.html_error_template()?
      +

      Provides a template that renders a stack trace in an HTML format, +providing an excerpt of code as well as substituting source template +filenames, line numbers and code for that of the originating source +template, as applicable.

      +

      The template’s default encoding_errors value is 'htmlentityreplace'. The +template has two options. With the full option disabled, only a section of +an HTML document is returned. With the css option disabled, the default +stylesheet won’t be included.

      +
      + +
      +
      +mako.exceptions.text_error_template(lookup=None)?
      +

      Provides a template that renders a stack trace in a similar format to +the Python interpreter, substituting source template filenames, line +numbers and code for that of the originating source template, as +applicable.

      +
      + +
      +
      + +
      + +
      + + + +
      + +
      + +
      + + + +
      +
      + + diff --git a/lib/mako-0.7.2/examples/bench/basic.py b/lib/mako-0.7.2/examples/bench/basic.py new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/examples/bench/basic.py @@ -0,0 +1,191 @@ +# basic.py - basic benchmarks adapted from Genshi +# Copyright (C) 2006 Edgewall Software +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# 3. The name of the author may not be used to endorse or promote +# products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE +# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from cgi import escape +import os +try: + from StringIO import StringIO +except ImportError: + from io import StringIO +import sys +import timeit + +def u(stringlit): + if sys.version_info >= (3,): + return stringlit + else: + return stringlit.decode('latin1') + +__all__ = ['mako', 'mako_inheritance', 'jinja2', 'jinja2_inheritance', + 'cheetah', 'django', 'myghty', 'genshi', 'kid'] + +# Templates content and constants +TITLE = 'Just a test' +USER = 'joe' +ITEMS = ['Number %d' % num for num in range(1, 15)] +U_ITEMS = [u(item) for item in ITEMS] + +def genshi(dirname, verbose=False): + from genshi.template import TemplateLoader + loader = TemplateLoader([dirname], auto_reload=False) + template = loader.load('template.html') + def render(): + data = dict(title=TITLE, user=USER, items=ITEMS) + return template.generate(**data).render('xhtml') + + if verbose: + print(render()) + return render + +def myghty(dirname, verbose=False): + from myghty import interp + interpreter = interp.Interpreter(component_root=dirname) + def render(): + data = dict(title=TITLE, user=USER, items=ITEMS) + buffer = StringIO() + interpreter.execute("template.myt", request_args=data, out_buffer=buffer) + return buffer.getvalue() + if verbose: + print(render()) + return render + +def mako(dirname, verbose=False): + from mako.template import Template + from mako.lookup import TemplateLookup + disable_unicode = (sys.version_info < (3,)) + lookup = TemplateLookup(directories=[dirname], filesystem_checks=False, disable_unicode=disable_unicode) + template = lookup.get_template('template.html') + def render(): + return template.render(title=TITLE, user=USER, list_items=U_ITEMS) + if verbose: + print(template.code + " " + render()) + return render +mako_inheritance = mako + +def jinja2(dirname, verbose=False): + from jinja2 import Environment, FileSystemLoader + env = Environment(loader=FileSystemLoader(dirname)) + template = env.get_template('template.html') + def render(): + return template.render(title=TITLE, user=USER, list_items=U_ITEMS) + if verbose: + print(render()) + return render +jinja2_inheritance = jinja2 + +def cheetah(dirname, verbose=False): + from Cheetah.Template import Template + filename = os.path.join(dirname, 'template.tmpl') + template = Template(file=filename) + def render(): + template.__dict__.update({'title': TITLE, 'user': USER, + 'list_items': U_ITEMS}) + return template.respond() + + if verbose: + print(dir(template)) + print(template.generatedModuleCode()) + print(render()) + return render + +def django(dirname, verbose=False): + from django.conf import settings + settings.configure(TEMPLATE_DIRS=[os.path.join(dirname, 'templates')]) + from django import template, templatetags + from django.template import loader + templatetags.__path__.append(os.path.join(dirname, 'templatetags')) + tmpl = loader.get_template('template.html') + + def render(): + data = {'title': TITLE, 'user': USER, 'items': ITEMS} + return tmpl.render(template.Context(data)) + + if verbose: + print(render()) + return render + +def kid(dirname, verbose=False): + import kid + kid.path = kid.TemplatePath([dirname]) + template = kid.Template(file='template.kid') + def render(): + template = kid.Template(file='template.kid', + title=TITLE, user=USER, items=ITEMS) + return template.serialize(output='xhtml') + + if verbose: + print(render()) + return render + + +def run(engines, number=2000, verbose=False): + basepath = os.path.abspath(os.path.dirname(__file__)) + for engine in engines: + dirname = os.path.join(basepath, engine) + if verbose: + print('%s:' % engine.capitalize()) + print('--------------------------------------------------------') + else: + sys.stdout.write('%s:' % engine.capitalize()) + t = timeit.Timer(setup='from __main__ import %s; render = %s(r"%s", %s)' + % (engine, engine, dirname, verbose), + stmt='render()') + + time = t.timeit(number=number) / number + if verbose: + print('--------------------------------------------------------') + print('%.2f ms' % (1000 * time)) + if verbose: + print('--------------------------------------------------------') + + +if __name__ == '__main__': + engines = [arg for arg in sys.argv[1:] if arg[0] != '-'] + if not engines: + engines = __all__ + + verbose = '-v' in sys.argv + + if '-p' in sys.argv: + try: + import hotshot, hotshot.stats + prof = hotshot.Profile("template.prof") + benchtime = prof.runcall(run, engines, number=100, verbose=verbose) + stats = hotshot.stats.load("template.prof") + except ImportError: + import cProfile, pstats + stmt = "run(%r, number=%r, verbose=%r)" % (engines, 1000, verbose) + cProfile.runctx(stmt, globals(), {}, "template.prof") + stats = pstats.Stats("template.prof") + stats.strip_dirs() + stats.sort_stats('time', 'calls') + stats.print_stats() + else: + run(engines, verbose=verbose) diff --git a/lib/mako-0.7.2/examples/bench/cheetah/footer.tmpl b/lib/mako-0.7.2/examples/bench/cheetah/footer.tmpl new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/examples/bench/cheetah/footer.tmpl @@ -0,0 +1,2 @@ + diff --git a/lib/mako-0.7.2/examples/bench/cheetah/header.tmpl b/lib/mako-0.7.2/examples/bench/cheetah/header.tmpl new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/examples/bench/cheetah/header.tmpl @@ -0,0 +1,5 @@ + + + diff --git a/lib/mako-0.7.2/examples/bench/cheetah/template.tmpl b/lib/mako-0.7.2/examples/bench/cheetah/template.tmpl new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/examples/bench/cheetah/template.tmpl @@ -0,0 +1,31 @@ + + + + ${title} + + + + #def greeting(name) +

      hello ${name}!

      + #end def + + #include "cheetah/header.tmpl" + + $greeting($user) + $greeting('me') + $greeting('world') + +

      Loop

      + #if $list_items +
        + #for $list_item in $list_items +
      • $list_item
      • + #end for +
      + #end if + + #include "cheetah/footer.tmpl" + + diff --git a/lib/mako-0.7.2/examples/bench/django/templatetags/__init__.py b/lib/mako-0.7.2/examples/bench/django/templatetags/__init__.py new file mode 100644 diff --git a/lib/mako-0.7.2/examples/bench/django/templatetags/bench.py b/lib/mako-0.7.2/examples/bench/django/templatetags/bench.py new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/examples/bench/django/templatetags/bench.py @@ -0,0 +1,8 @@ +from django.template import Library, Node, resolve_variable +from django.utils.html import escape + +register = Library() + +def greeting(name): + return 'Hello, %s!' % escape(name) +greeting = register.simple_tag(greeting) diff --git a/lib/mako-0.7.2/examples/bench/kid/base.kid b/lib/mako-0.7.2/examples/bench/kid/base.kid new file mode 100644 --- /dev/null +++ b/lib/mako-0.7.2/examples/bench/kid/base.kid @@ -0,0 +1,15 @@ + + +

      + Hello, ${name}! +

      + + + + ${item} +