From python-checkins at python.org Thu Nov 1 00:03:33 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Nov 2012 00:03:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_check_return_v?= =?utf-8?q?alue_of_=5FPyUnicode=5FAsString?= Message-ID: <3XsQ850RQhzPbJ@mail.python.org> http://hg.python.org/cpython/rev/6964a9b6c1ea changeset: 80141:6964a9b6c1ea branch: 3.3 parent: 80120:4b842da2b0ac user: Benjamin Peterson date: Wed Oct 31 19:01:42 2012 -0400 summary: check return value of _PyUnicode_AsString files: Python/symtable.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1202,12 +1202,14 @@ asdl_seq *seq = s->v.Global.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = _PyUnicode_AsString(name); long cur = symtable_lookup(st, name); if (cur < 0) return 0; if (cur & (DEF_LOCAL | USE)) { char buf[256]; + char *c_name = _PyUnicode_AsString(name); + if (!c_name) + return 0; if (cur & DEF_LOCAL) PyOS_snprintf(buf, sizeof(buf), GLOBAL_AFTER_ASSIGN, @@ -1229,12 +1231,14 @@ asdl_seq *seq = s->v.Nonlocal.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = _PyUnicode_AsString(name); long cur = symtable_lookup(st, name); if (cur < 0) return 0; if (cur & (DEF_LOCAL | USE)) { char buf[256]; + char *c_name = _PyUnicode_AsString(name); + if (!c_name) + return 0; if (cur & DEF_LOCAL) PyOS_snprintf(buf, sizeof(buf), NONLOCAL_AFTER_ASSIGN, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 00:03:34 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Nov 2012 00:03:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4z?= Message-ID: <3XsQ8630XjzPbJ@mail.python.org> http://hg.python.org/cpython/rev/9c2df50b4fe0 changeset: 80142:9c2df50b4fe0 parent: 80121:1698d1ab0b0a parent: 80141:6964a9b6c1ea user: Benjamin Peterson date: Wed Oct 31 19:01:48 2012 -0400 summary: merge 3.3 files: Python/symtable.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -1202,12 +1202,14 @@ asdl_seq *seq = s->v.Global.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = _PyUnicode_AsString(name); long cur = symtable_lookup(st, name); if (cur < 0) return 0; if (cur & (DEF_LOCAL | USE)) { char buf[256]; + char *c_name = _PyUnicode_AsString(name); + if (!c_name) + return 0; if (cur & DEF_LOCAL) PyOS_snprintf(buf, sizeof(buf), GLOBAL_AFTER_ASSIGN, @@ -1229,12 +1231,14 @@ asdl_seq *seq = s->v.Nonlocal.names; for (i = 0; i < asdl_seq_LEN(seq); i++) { identifier name = (identifier)asdl_seq_GET(seq, i); - char *c_name = _PyUnicode_AsString(name); long cur = symtable_lookup(st, name); if (cur < 0) return 0; if (cur & (DEF_LOCAL | USE)) { char buf[256]; + char *c_name = _PyUnicode_AsString(name); + if (!c_name) + return 0; if (cur & DEF_LOCAL) PyOS_snprintf(buf, sizeof(buf), NONLOCAL_AFTER_ASSIGN, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 00:03:36 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Nov 2012 00:03:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuMyk6?= =?utf-8?q?_merge_heads?= Message-ID: <3XsQ880vyMzPh0@mail.python.org> http://hg.python.org/cpython/rev/3c249adc78aa changeset: 80143:3c249adc78aa branch: 3.3 parent: 80141:6964a9b6c1ea parent: 80134:f3dd84feeb58 user: Benjamin Peterson date: Wed Oct 31 19:02:18 2012 -0400 summary: merge heads files: Doc/library/decimal.rst | 21 +- Doc/library/profile.rst | 231 +++++++++++++++------------ Lib/test/test_bisect.py | 2 +- 3 files changed, 146 insertions(+), 108 deletions(-) diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -750,12 +750,21 @@ .. method:: remainder_near(other[, context]) - Compute the modulo as either a positive or negative value depending on - which is closest to zero. For instance, ``Decimal(10).remainder_near(6)`` - returns ``Decimal('-2')`` which is closer to zero than ``Decimal('4')``. - - If both are equally close, the one chosen will have the same sign as - *self*. + Return the remainder from dividing *self* by *other*. This differs from + ``self % other`` in that the sign of the remainder is chosen so as to + minimize its absolute value. More precisely, the return value is + ``self - n * other`` where ``n`` is the integer nearest to the exact + value of ``self / other``, and if two integers are equally near then the + even one is chosen. + + If the result is zero then its sign will be the sign of *self*. + + >>> Decimal(18).remainder_near(Decimal(10)) + Decimal('-2') + >>> Decimal(25).remainder_near(Decimal(10)) + Decimal('5') + >>> Decimal(35).remainder_near(Decimal(10)) + Decimal('-5') .. method:: rotate(other[, context]) diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -240,11 +240,12 @@ 43/3 0.533 0.012 0.749 0.250 pobject.py:99(evaluate) ... - The first line indicates that 2706 calls were monitored. Of those calls, 2004 - were :dfn:`primitive`. We define :dfn:`primitive` to mean that the call was not - induced via recursion. The next line: ``Ordered by: standard name``, indicates - that the text string in the far right column was used to sort the output. The - column headings include: + The first line indicates that 2706 calls were monitored. Of those + calls, 2004 were :dfn:`primitive`. We define :dfn:`primitive` to + mean that the call was not induced via recursion. The next line: + ``Ordered by: standard name``, indicates that the text string in + the far right column was used to sort the output. The column + headings include: ncalls for the number of calls, @@ -266,14 +267,14 @@ filename:lineno(function) provides the respective data of each function - When there are two numbers in the first column (for example, ``43/3``), then the - latter is the number of primitive calls, and the former is the actual number of - calls. Note that when the function does not recurse, these two values are the - same, and only the single figure is printed. + When there are two numbers in the first column (for example, + ``43/3``), then the latter is the number of primitive calls, and + the former is the actual number of calls. Note that when the + function does not recurse, these two values are the same, and only + the single figure is printed. - If *sort* is given, it can be one of ``'stdname'`` (sort by filename:lineno), - ``'calls'`` (sort by number of calls), ``'time'`` (sort by total time) or - ``'cumulative'`` (sort by cumulative time). The default is ``'stdname'``. + If *sort* is given, it can be one of values allowed for *key* + parameter from :meth:`pstats.Stats.sort_stats`. .. function:: runctx(command, globals, locals, filename=None) @@ -291,19 +292,22 @@ .. class:: Stats(*filenames, stream=sys.stdout) - This class constructor creates an instance of a "statistics object" from a - *filename* (or set of filenames). :class:`Stats` objects are manipulated by - methods, in order to print useful reports. You may specify an alternate output - stream by giving the keyword argument, ``stream``. + This class constructor creates an instance of a "statistics object" + from a *filename* (or set of filenames). :class:`Stats` objects + are manipulated by methods, in order to print useful reports. You + may specify an alternate output stream by giving the keyword + argument, ``stream``. - The file selected by the above constructor must have been created by the - corresponding version of :mod:`profile` or :mod:`cProfile`. To be specific, - there is *no* file compatibility guaranteed with future versions of this - profiler, and there is no compatibility with files produced by other profilers. - If several files are provided, all the statistics for identical functions will - be coalesced, so that an overall view of several processes can be considered in - a single report. If additional files need to be combined with data in an - existing :class:`Stats` object, the :meth:`add` method can be used. + The file selected by the above constructor must have been created + by the corresponding version of :mod:`profile` or :mod:`cProfile`. + To be specific, there is *no* file compatibility guaranteed with + future versions of this profiler, and there is no compatibility + with files produced by other profilers. If several files are + provided, all the statistics for identical functions will be + coalesced, so that an overall view of several processes can be + considered in a single report. If additional files need to be + combined with data in an existing :class:`Stats` object, the + :meth:`add` method can be used. .. (such as the old system profiler). @@ -318,15 +322,17 @@ .. method:: Stats.strip_dirs() - This method for the :class:`Stats` class removes all leading path information - from file names. It is very useful in reducing the size of the printout to fit - within (close to) 80 columns. This method modifies the object, and the stripped - information is lost. After performing a strip operation, the object is - considered to have its entries in a "random" order, as it was just after object - initialization and loading. If :meth:`strip_dirs` causes two function names to - be indistinguishable (they are on the same line of the same filename, and have - the same function name), then the statistics for these two entries are - accumulated into a single entry. + This method for the :class:`Stats` class removes all leading path + information from file names. It is very useful in reducing the + size of the printout to fit within (close to) 80 columns. This + method modifies the object, and the stripped information is lost. + After performing a strip operation, the object is considered to + have its entries in a "random" order, as it was just after object + initialization and loading. If :meth:`strip_dirs` causes two + function names to be indistinguishable (they are on the same line + of the same filename, and have the same function name), then the + statistics for these two entries are accumulated into a single + entry. .. method:: Stats.add(*filenames) @@ -340,23 +346,25 @@ .. method:: Stats.dump_stats(filename) - Save the data loaded into the :class:`Stats` object to a file named *filename*. - The file is created if it does not exist, and is overwritten if it already - exists. This is equivalent to the method of the same name on the - :class:`profile.Profile` and :class:`cProfile.Profile` classes. + Save the data loaded into the :class:`Stats` object to a file named + *filename*. The file is created if it does not exist, and is + overwritten if it already exists. This is equivalent to the method + of the same name on the :class:`profile.Profile` and + :class:`cProfile.Profile` classes. .. method:: Stats.sort_stats(*keys) - This method modifies the :class:`Stats` object by sorting it according to the - supplied criteria. The argument is typically a string identifying the basis of - a sort (example: ``'time'`` or ``'name'``). + This method modifies the :class:`Stats` object by sorting it + according to the supplied criteria. The argument is typically a + string identifying the basis of a sort (example: ``'time'`` or + ``'name'``). - When more than one key is provided, then additional keys are used as secondary - criteria when there is equality in all keys selected before them. For example, - ``sort_stats('name', 'file')`` will sort all the entries according to their - function name, and resolve all ties (identical function names) by sorting by - file name. + When more than one key is provided, then additional keys are used + as secondary criteria when there is equality in all keys selected + before them. For example, ``sort_stats('name', 'file')`` will sort + all the entries according to their function name, and resolve all + ties (identical function names) by sorting by file name. Abbreviations can be used for any key names, as long as the abbreviation is unambiguous. The following are the keys currently defined: @@ -368,10 +376,16 @@ +------------------+----------------------+ | ``'cumulative'`` | cumulative time | +------------------+----------------------+ + | ``'cumtime'`` | cumulative time | + +------------------+----------------------+ | ``'file'`` | file name | +------------------+----------------------+ + | ``'filename'`` | file name | + +------------------+----------------------+ | ``'module'`` | file name | +------------------+----------------------+ + | ``'ncalls'`` | call count | + +------------------+----------------------+ | ``'pcalls'`` | primitive call count | +------------------+----------------------+ | ``'line'`` | line number | @@ -384,51 +398,60 @@ +------------------+----------------------+ | ``'time'`` | internal time | +------------------+----------------------+ + | ``'tottime'`` | internal time | + +------------------+----------------------+ - Note that all sorts on statistics are in descending order (placing most time - consuming items first), where as name, file, and line number searches are in - ascending order (alphabetical). The subtle distinction between ``'nfl'`` and - ``'stdname'`` is that the standard name is a sort of the name as printed, which - means that the embedded line numbers get compared in an odd way. For example, - lines 3, 20, and 40 would (if the file names were the same) appear in the string - order 20, 3 and 40. In contrast, ``'nfl'`` does a numeric compare of the line - numbers. In fact, ``sort_stats('nfl')`` is the same as ``sort_stats('name', - 'file', 'line')``. + Note that all sorts on statistics are in descending order (placing + most time consuming items first), where as name, file, and line + number searches are in ascending order (alphabetical). The subtle + distinction between ``'nfl'`` and ``'stdname'`` is that the + standard name is a sort of the name as printed, which means that + the embedded line numbers get compared in an odd way. For example, + lines 3, 20, and 40 would (if the file names were the same) appear + in the string order 20, 3 and 40. In contrast, ``'nfl'`` does a + numeric compare of the line numbers. In fact, + ``sort_stats('nfl')`` is the same as ``sort_stats('name', 'file', + 'line')``. - For backward-compatibility reasons, the numeric arguments ``-1``, ``0``, ``1``, - and ``2`` are permitted. They are interpreted as ``'stdname'``, ``'calls'``, - ``'time'``, and ``'cumulative'`` respectively. If this old style format - (numeric) is used, only one sort key (the numeric key) will be used, and - additional arguments will be silently ignored. + For backward-compatibility reasons, the numeric arguments ``-1``, + ``0``, ``1``, and ``2`` are permitted. They are interpreted as + ``'stdname'``, ``'calls'``, ``'time'``, and ``'cumulative'`` + respectively. If this old style format (numeric) is used, only one + sort key (the numeric key) will be used, and additional arguments + will be silently ignored. .. For compatibility with the old profiler, .. method:: Stats.reverse_order() - This method for the :class:`Stats` class reverses the ordering of the basic list - within the object. Note that by default ascending vs descending order is - properly selected based on the sort key of choice. + This method for the :class:`Stats` class reverses the ordering of + the basic list within the object. Note that by default ascending + vs descending order is properly selected based on the sort key of + choice. .. This method is provided primarily for compatibility with the old profiler. .. method:: Stats.print_stats(*restrictions) - This method for the :class:`Stats` class prints out a report as described in the - :func:`profile.run` definition. + This method for the :class:`Stats` class prints out a report as + described in the :func:`profile.run` definition. - The order of the printing is based on the last :meth:`sort_stats` operation done - on the object (subject to caveats in :meth:`add` and :meth:`strip_dirs`). + The order of the printing is based on the last :meth:`sort_stats` + operation done on the object (subject to caveats in :meth:`add` and + :meth:`strip_dirs`). - The arguments provided (if any) can be used to limit the list down to the - significant entries. Initially, the list is taken to be the complete set of - profiled functions. Each restriction is either an integer (to select a count of - lines), or a decimal fraction between 0.0 and 1.0 inclusive (to select a - percentage of lines), or a regular expression (to pattern match the standard - name that is printed; as of Python 1.5b1, this uses the Perl-style regular - expression syntax defined by the :mod:`re` module). If several restrictions are - provided, then they are applied sequentially. For example:: + The arguments provided (if any) can be used to limit the list down + to the significant entries. Initially, the list is taken to be the + complete set of profiled functions. Each restriction is either an + integer (to select a count of lines), or a decimal fraction between + 0.0 and 1.0 inclusive (to select a percentage of lines), or a + regular expression (to pattern match the standard name that is + printed; as of Python 1.5b1, this uses the Perl-style regular + expression syntax defined by the :mod:`re` module). If several + restrictions are provided, then they are applied sequentially. For + example:: print_stats(.1, 'foo:') @@ -455,17 +478,19 @@ non-parenthesized number repeats the cumulative time spent in the function at the right. - * With :mod:`cProfile`, each caller is preceded by three numbers: the number of - times this specific call was made, and the total and cumulative times spent in - the current function while it was invoked by this specific caller. + * With :mod:`cProfile`, each caller is preceded by three numbers: + the number of times this specific call was made, and the total + and cumulative times spent in the current function while it was + invoked by this specific caller. .. method:: Stats.print_callees(*restrictions) - This method for the :class:`Stats` class prints a list of all function that were - called by the indicated function. Aside from this reversal of direction of - calls (re: called vs was called by), the arguments and ordering are identical to - the :meth:`print_callers` method. + This method for the :class:`Stats` class prints a list of all + function that were called by the indicated function. Aside from + this reversal of direction of calls (re: called vs was called by), + the arguments and ordering are identical to the + :meth:`print_callers` method. .. _profile-limits: @@ -566,29 +591,33 @@ The resulting profiler will then call :func:`your_time_func`. :class:`profile.Profile` - :func:`your_time_func` should return a single number, or a list of numbers whose - sum is the current time (like what :func:`os.times` returns). If the function - returns a single time number, or the list of returned numbers has length 2, then - you will get an especially fast version of the dispatch routine. + :func:`your_time_func` should return a single number, or a list of + numbers whose sum is the current time (like what :func:`os.times` + returns). If the function returns a single time number, or the + list of returned numbers has length 2, then you will get an + especially fast version of the dispatch routine. - Be warned that you should calibrate the profiler class for the timer function - that you choose. For most machines, a timer that returns a lone integer value - will provide the best results in terms of low overhead during profiling. - (:func:`os.times` is *pretty* bad, as it returns a tuple of floating point - values). If you want to substitute a better timer in the cleanest fashion, - derive a class and hardwire a replacement dispatch method that best handles your - timer call, along with the appropriate calibration constant. + Be warned that you should calibrate the profiler class for the + timer function that you choose. For most machines, a timer that + returns a lone integer value will provide the best results in terms + of low overhead during profiling. (:func:`os.times` is *pretty* + bad, as it returns a tuple of floating point values). If you want + to substitute a better timer in the cleanest fashion, derive a + class and hardwire a replacement dispatch method that best handles + your timer call, along with the appropriate calibration constant. :class:`cProfile.Profile` - :func:`your_time_func` should return a single number. If it returns - integers, you can also invoke the class constructor with a second argument - specifying the real duration of one unit of time. For example, if - :func:`your_integer_time_func` returns times measured in thousands of seconds, - you would construct the :class:`Profile` instance as follows:: + :func:`your_time_func` should return a single number. If it + returns integers, you can also invoke the class constructor with a + second argument specifying the real duration of one unit of time. + For example, if :func:`your_integer_time_func` returns times + measured in thousands of seconds, you would construct the + :class:`Profile` instance as follows:: pr = profile.Profile(your_integer_time_func, 0.001) - As the :mod:`cProfile.Profile` class cannot be calibrated, custom timer - functions should be used with care and should be as fast as possible. For the - best results with a custom timer, it might be necessary to hard-code it in the C - source of the internal :mod:`_lsprof` module. + As the :mod:`cProfile.Profile` class cannot be calibrated, custom + timer functions should be used with care and should be as fast as + possible. For the best results with a custom timer, it might be + necessary to hard-code it in the C source of the internal + :mod:`_lsprof` module. diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -239,7 +239,7 @@ else: f = self.module.insort_right f(insorted, digit) - self.assertEqual(sorted(insorted), insorted) + self.assertEqual(sorted(insorted), insorted) def test_backcompatibility(self): self.assertEqual(self.module.insort, self.module.insort_right) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 00:03:38 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Nov 2012 00:03:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <3XsQ8B0TX3zPhl@mail.python.org> http://hg.python.org/cpython/rev/e3eb94389e95 changeset: 80144:e3eb94389e95 parent: 80142:9c2df50b4fe0 parent: 80140:b3434c1ae503 user: Benjamin Peterson date: Wed Oct 31 19:02:24 2012 -0400 summary: merge heads files: Doc/library/decimal.rst | 21 +- Doc/library/profile.rst | 231 ++++++++++++---------- Lib/test/support.py | 2 +- Lib/test/test_bisect.py | 2 +- Lib/test/test_genericpath.py | 12 +- Lib/test/test_os.py | 83 ++++--- Modules/posixmodule.c | 99 ++------- 7 files changed, 224 insertions(+), 226 deletions(-) diff --git a/Doc/library/decimal.rst b/Doc/library/decimal.rst --- a/Doc/library/decimal.rst +++ b/Doc/library/decimal.rst @@ -750,12 +750,21 @@ .. method:: remainder_near(other[, context]) - Compute the modulo as either a positive or negative value depending on - which is closest to zero. For instance, ``Decimal(10).remainder_near(6)`` - returns ``Decimal('-2')`` which is closer to zero than ``Decimal('4')``. - - If both are equally close, the one chosen will have the same sign as - *self*. + Return the remainder from dividing *self* by *other*. This differs from + ``self % other`` in that the sign of the remainder is chosen so as to + minimize its absolute value. More precisely, the return value is + ``self - n * other`` where ``n`` is the integer nearest to the exact + value of ``self / other``, and if two integers are equally near then the + even one is chosen. + + If the result is zero then its sign will be the sign of *self*. + + >>> Decimal(18).remainder_near(Decimal(10)) + Decimal('-2') + >>> Decimal(25).remainder_near(Decimal(10)) + Decimal('5') + >>> Decimal(35).remainder_near(Decimal(10)) + Decimal('-5') .. method:: rotate(other[, context]) diff --git a/Doc/library/profile.rst b/Doc/library/profile.rst --- a/Doc/library/profile.rst +++ b/Doc/library/profile.rst @@ -240,11 +240,12 @@ 43/3 0.533 0.012 0.749 0.250 pobject.py:99(evaluate) ... - The first line indicates that 2706 calls were monitored. Of those calls, 2004 - were :dfn:`primitive`. We define :dfn:`primitive` to mean that the call was not - induced via recursion. The next line: ``Ordered by: standard name``, indicates - that the text string in the far right column was used to sort the output. The - column headings include: + The first line indicates that 2706 calls were monitored. Of those + calls, 2004 were :dfn:`primitive`. We define :dfn:`primitive` to + mean that the call was not induced via recursion. The next line: + ``Ordered by: standard name``, indicates that the text string in + the far right column was used to sort the output. The column + headings include: ncalls for the number of calls, @@ -266,14 +267,14 @@ filename:lineno(function) provides the respective data of each function - When there are two numbers in the first column (for example, ``43/3``), then the - latter is the number of primitive calls, and the former is the actual number of - calls. Note that when the function does not recurse, these two values are the - same, and only the single figure is printed. + When there are two numbers in the first column (for example, + ``43/3``), then the latter is the number of primitive calls, and + the former is the actual number of calls. Note that when the + function does not recurse, these two values are the same, and only + the single figure is printed. - If *sort* is given, it can be one of ``'stdname'`` (sort by filename:lineno), - ``'calls'`` (sort by number of calls), ``'time'`` (sort by total time) or - ``'cumulative'`` (sort by cumulative time). The default is ``'stdname'``. + If *sort* is given, it can be one of values allowed for *key* + parameter from :meth:`pstats.Stats.sort_stats`. .. function:: runctx(command, globals, locals, filename=None) @@ -291,19 +292,22 @@ .. class:: Stats(*filenames, stream=sys.stdout) - This class constructor creates an instance of a "statistics object" from a - *filename* (or set of filenames). :class:`Stats` objects are manipulated by - methods, in order to print useful reports. You may specify an alternate output - stream by giving the keyword argument, ``stream``. + This class constructor creates an instance of a "statistics object" + from a *filename* (or set of filenames). :class:`Stats` objects + are manipulated by methods, in order to print useful reports. You + may specify an alternate output stream by giving the keyword + argument, ``stream``. - The file selected by the above constructor must have been created by the - corresponding version of :mod:`profile` or :mod:`cProfile`. To be specific, - there is *no* file compatibility guaranteed with future versions of this - profiler, and there is no compatibility with files produced by other profilers. - If several files are provided, all the statistics for identical functions will - be coalesced, so that an overall view of several processes can be considered in - a single report. If additional files need to be combined with data in an - existing :class:`Stats` object, the :meth:`add` method can be used. + The file selected by the above constructor must have been created + by the corresponding version of :mod:`profile` or :mod:`cProfile`. + To be specific, there is *no* file compatibility guaranteed with + future versions of this profiler, and there is no compatibility + with files produced by other profilers. If several files are + provided, all the statistics for identical functions will be + coalesced, so that an overall view of several processes can be + considered in a single report. If additional files need to be + combined with data in an existing :class:`Stats` object, the + :meth:`add` method can be used. .. (such as the old system profiler). @@ -318,15 +322,17 @@ .. method:: Stats.strip_dirs() - This method for the :class:`Stats` class removes all leading path information - from file names. It is very useful in reducing the size of the printout to fit - within (close to) 80 columns. This method modifies the object, and the stripped - information is lost. After performing a strip operation, the object is - considered to have its entries in a "random" order, as it was just after object - initialization and loading. If :meth:`strip_dirs` causes two function names to - be indistinguishable (they are on the same line of the same filename, and have - the same function name), then the statistics for these two entries are - accumulated into a single entry. + This method for the :class:`Stats` class removes all leading path + information from file names. It is very useful in reducing the + size of the printout to fit within (close to) 80 columns. This + method modifies the object, and the stripped information is lost. + After performing a strip operation, the object is considered to + have its entries in a "random" order, as it was just after object + initialization and loading. If :meth:`strip_dirs` causes two + function names to be indistinguishable (they are on the same line + of the same filename, and have the same function name), then the + statistics for these two entries are accumulated into a single + entry. .. method:: Stats.add(*filenames) @@ -340,23 +346,25 @@ .. method:: Stats.dump_stats(filename) - Save the data loaded into the :class:`Stats` object to a file named *filename*. - The file is created if it does not exist, and is overwritten if it already - exists. This is equivalent to the method of the same name on the - :class:`profile.Profile` and :class:`cProfile.Profile` classes. + Save the data loaded into the :class:`Stats` object to a file named + *filename*. The file is created if it does not exist, and is + overwritten if it already exists. This is equivalent to the method + of the same name on the :class:`profile.Profile` and + :class:`cProfile.Profile` classes. .. method:: Stats.sort_stats(*keys) - This method modifies the :class:`Stats` object by sorting it according to the - supplied criteria. The argument is typically a string identifying the basis of - a sort (example: ``'time'`` or ``'name'``). + This method modifies the :class:`Stats` object by sorting it + according to the supplied criteria. The argument is typically a + string identifying the basis of a sort (example: ``'time'`` or + ``'name'``). - When more than one key is provided, then additional keys are used as secondary - criteria when there is equality in all keys selected before them. For example, - ``sort_stats('name', 'file')`` will sort all the entries according to their - function name, and resolve all ties (identical function names) by sorting by - file name. + When more than one key is provided, then additional keys are used + as secondary criteria when there is equality in all keys selected + before them. For example, ``sort_stats('name', 'file')`` will sort + all the entries according to their function name, and resolve all + ties (identical function names) by sorting by file name. Abbreviations can be used for any key names, as long as the abbreviation is unambiguous. The following are the keys currently defined: @@ -368,10 +376,16 @@ +------------------+----------------------+ | ``'cumulative'`` | cumulative time | +------------------+----------------------+ + | ``'cumtime'`` | cumulative time | + +------------------+----------------------+ | ``'file'`` | file name | +------------------+----------------------+ + | ``'filename'`` | file name | + +------------------+----------------------+ | ``'module'`` | file name | +------------------+----------------------+ + | ``'ncalls'`` | call count | + +------------------+----------------------+ | ``'pcalls'`` | primitive call count | +------------------+----------------------+ | ``'line'`` | line number | @@ -384,51 +398,60 @@ +------------------+----------------------+ | ``'time'`` | internal time | +------------------+----------------------+ + | ``'tottime'`` | internal time | + +------------------+----------------------+ - Note that all sorts on statistics are in descending order (placing most time - consuming items first), where as name, file, and line number searches are in - ascending order (alphabetical). The subtle distinction between ``'nfl'`` and - ``'stdname'`` is that the standard name is a sort of the name as printed, which - means that the embedded line numbers get compared in an odd way. For example, - lines 3, 20, and 40 would (if the file names were the same) appear in the string - order 20, 3 and 40. In contrast, ``'nfl'`` does a numeric compare of the line - numbers. In fact, ``sort_stats('nfl')`` is the same as ``sort_stats('name', - 'file', 'line')``. + Note that all sorts on statistics are in descending order (placing + most time consuming items first), where as name, file, and line + number searches are in ascending order (alphabetical). The subtle + distinction between ``'nfl'`` and ``'stdname'`` is that the + standard name is a sort of the name as printed, which means that + the embedded line numbers get compared in an odd way. For example, + lines 3, 20, and 40 would (if the file names were the same) appear + in the string order 20, 3 and 40. In contrast, ``'nfl'`` does a + numeric compare of the line numbers. In fact, + ``sort_stats('nfl')`` is the same as ``sort_stats('name', 'file', + 'line')``. - For backward-compatibility reasons, the numeric arguments ``-1``, ``0``, ``1``, - and ``2`` are permitted. They are interpreted as ``'stdname'``, ``'calls'``, - ``'time'``, and ``'cumulative'`` respectively. If this old style format - (numeric) is used, only one sort key (the numeric key) will be used, and - additional arguments will be silently ignored. + For backward-compatibility reasons, the numeric arguments ``-1``, + ``0``, ``1``, and ``2`` are permitted. They are interpreted as + ``'stdname'``, ``'calls'``, ``'time'``, and ``'cumulative'`` + respectively. If this old style format (numeric) is used, only one + sort key (the numeric key) will be used, and additional arguments + will be silently ignored. .. For compatibility with the old profiler, .. method:: Stats.reverse_order() - This method for the :class:`Stats` class reverses the ordering of the basic list - within the object. Note that by default ascending vs descending order is - properly selected based on the sort key of choice. + This method for the :class:`Stats` class reverses the ordering of + the basic list within the object. Note that by default ascending + vs descending order is properly selected based on the sort key of + choice. .. This method is provided primarily for compatibility with the old profiler. .. method:: Stats.print_stats(*restrictions) - This method for the :class:`Stats` class prints out a report as described in the - :func:`profile.run` definition. + This method for the :class:`Stats` class prints out a report as + described in the :func:`profile.run` definition. - The order of the printing is based on the last :meth:`sort_stats` operation done - on the object (subject to caveats in :meth:`add` and :meth:`strip_dirs`). + The order of the printing is based on the last :meth:`sort_stats` + operation done on the object (subject to caveats in :meth:`add` and + :meth:`strip_dirs`). - The arguments provided (if any) can be used to limit the list down to the - significant entries. Initially, the list is taken to be the complete set of - profiled functions. Each restriction is either an integer (to select a count of - lines), or a decimal fraction between 0.0 and 1.0 inclusive (to select a - percentage of lines), or a regular expression (to pattern match the standard - name that is printed; as of Python 1.5b1, this uses the Perl-style regular - expression syntax defined by the :mod:`re` module). If several restrictions are - provided, then they are applied sequentially. For example:: + The arguments provided (if any) can be used to limit the list down + to the significant entries. Initially, the list is taken to be the + complete set of profiled functions. Each restriction is either an + integer (to select a count of lines), or a decimal fraction between + 0.0 and 1.0 inclusive (to select a percentage of lines), or a + regular expression (to pattern match the standard name that is + printed; as of Python 1.5b1, this uses the Perl-style regular + expression syntax defined by the :mod:`re` module). If several + restrictions are provided, then they are applied sequentially. For + example:: print_stats(.1, 'foo:') @@ -455,17 +478,19 @@ non-parenthesized number repeats the cumulative time spent in the function at the right. - * With :mod:`cProfile`, each caller is preceded by three numbers: the number of - times this specific call was made, and the total and cumulative times spent in - the current function while it was invoked by this specific caller. + * With :mod:`cProfile`, each caller is preceded by three numbers: + the number of times this specific call was made, and the total + and cumulative times spent in the current function while it was + invoked by this specific caller. .. method:: Stats.print_callees(*restrictions) - This method for the :class:`Stats` class prints a list of all function that were - called by the indicated function. Aside from this reversal of direction of - calls (re: called vs was called by), the arguments and ordering are identical to - the :meth:`print_callers` method. + This method for the :class:`Stats` class prints a list of all + function that were called by the indicated function. Aside from + this reversal of direction of calls (re: called vs was called by), + the arguments and ordering are identical to the + :meth:`print_callers` method. .. _profile-limits: @@ -566,29 +591,33 @@ The resulting profiler will then call :func:`your_time_func`. :class:`profile.Profile` - :func:`your_time_func` should return a single number, or a list of numbers whose - sum is the current time (like what :func:`os.times` returns). If the function - returns a single time number, or the list of returned numbers has length 2, then - you will get an especially fast version of the dispatch routine. + :func:`your_time_func` should return a single number, or a list of + numbers whose sum is the current time (like what :func:`os.times` + returns). If the function returns a single time number, or the + list of returned numbers has length 2, then you will get an + especially fast version of the dispatch routine. - Be warned that you should calibrate the profiler class for the timer function - that you choose. For most machines, a timer that returns a lone integer value - will provide the best results in terms of low overhead during profiling. - (:func:`os.times` is *pretty* bad, as it returns a tuple of floating point - values). If you want to substitute a better timer in the cleanest fashion, - derive a class and hardwire a replacement dispatch method that best handles your - timer call, along with the appropriate calibration constant. + Be warned that you should calibrate the profiler class for the + timer function that you choose. For most machines, a timer that + returns a lone integer value will provide the best results in terms + of low overhead during profiling. (:func:`os.times` is *pretty* + bad, as it returns a tuple of floating point values). If you want + to substitute a better timer in the cleanest fashion, derive a + class and hardwire a replacement dispatch method that best handles + your timer call, along with the appropriate calibration constant. :class:`cProfile.Profile` - :func:`your_time_func` should return a single number. If it returns - integers, you can also invoke the class constructor with a second argument - specifying the real duration of one unit of time. For example, if - :func:`your_integer_time_func` returns times measured in thousands of seconds, - you would construct the :class:`Profile` instance as follows:: + :func:`your_time_func` should return a single number. If it + returns integers, you can also invoke the class constructor with a + second argument specifying the real duration of one unit of time. + For example, if :func:`your_integer_time_func` returns times + measured in thousands of seconds, you would construct the + :class:`Profile` instance as follows:: pr = profile.Profile(your_integer_time_func, 0.001) - As the :mod:`cProfile.Profile` class cannot be calibrated, custom timer - functions should be used with care and should be as fast as possible. For the - best results with a custom timer, it might be necessary to hard-code it in the C - source of the internal :mod:`_lsprof` module. + As the :mod:`cProfile.Profile` class cannot be calibrated, custom + timer functions should be used with care and should be as fast as + possible. For the best results with a custom timer, it might be + necessary to hard-code it in the C source of the internal + :mod:`_lsprof` module. diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -654,7 +654,7 @@ for name in (b'abc\xff', b'\xe7w\xf0'): try: os.fsdecode(name) - except UnicodeDecodeErorr: + except UnicodeDecodeError: TESTFN_UNDECODABLE = name break diff --git a/Lib/test/test_bisect.py b/Lib/test/test_bisect.py --- a/Lib/test/test_bisect.py +++ b/Lib/test/test_bisect.py @@ -239,7 +239,7 @@ else: f = self.module.insort_right f(insorted, digit) - self.assertEqual(sorted(insorted), insorted) + self.assertEqual(sorted(insorted), insorted) def test_backcompatibility(self): self.assertEqual(self.module.insort, self.module.insort_right) diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -311,14 +311,10 @@ @unittest.skipIf(sys.platform == 'darwin', "Mac OS X denies the creation of a directory with an invalid utf8 name") def test_nonascii_abspath(self): - name = b'\xe7w\xf0' - if sys.platform == 'win32': - try: - os.fsdecode(name) - except UnicodeDecodeError: - self.skipTest("the filename %a is not decodable " - "from the ANSI code page %s" - % (name, sys.getfilesystemencoding())) + if support.TESTFN_UNDECODABLE: + name = support.TESTFN_UNDECODABLE + else: + name = b'a\xffb\xe7w\xf0' # Test non-ASCII, non-UTF8 bytes in the path. with warnings.catch_warnings(): diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2051,65 +2051,82 @@ class Str(str): pass - self.filenames = [] + self.bytes_filenames = [] + self.unicode_filenames = [] if support.TESTFN_UNENCODABLE is not None: decoded = support.TESTFN_UNENCODABLE else: decoded = support.TESTFN - self.filenames.append(decoded) - self.filenames.append(Str(decoded)) + self.unicode_filenames.append(decoded) + self.unicode_filenames.append(Str(decoded)) if support.TESTFN_UNDECODABLE is not None: encoded = support.TESTFN_UNDECODABLE else: encoded = os.fsencode(support.TESTFN) - self.filenames.append(encoded) - self.filenames.append(memoryview(encoded)) + self.bytes_filenames.append(encoded) + self.bytes_filenames.append(memoryview(encoded)) + + self.filenames = self.bytes_filenames + self.unicode_filenames def test_oserror_filename(self): funcs = [ - (os.chdir,), - (os.chmod, 0o777), - (os.lchown, 0, 0), - (os.listdir,), - (os.lstat,), - (os.open, os.O_RDONLY), - (os.rename, "dst"), - (os.replace, "dst"), - (os.rmdir,), - (os.stat,), - (os.truncate, 0), - (os.unlink,), + (self.filenames, os.chdir,), + (self.filenames, os.chmod, 0o777), + (self.filenames, os.listdir,), + (self.filenames, os.lstat,), + (self.filenames, os.open, os.O_RDONLY), + (self.filenames, os.rmdir,), + (self.filenames, os.stat,), + (self.filenames, os.unlink,), ] - if hasattr(os, "chown"): - funcs.append((os.chown, 0, 0)) if sys.platform == "win32": funcs.extend(( - (os._getfullpathname,), - (os._isdir,), + (self.bytes_filenames, os.rename, b"dst"), + (self.bytes_filenames, os.replace, b"dst"), + (self.unicode_filenames, os.rename, "dst"), + (self.unicode_filenames, os.replace, "dst"), )) + else: + funcs.extend(( + (self.filenames, os.rename, "dst"), + (self.filenames, os.replace, "dst"), + )) + if hasattr(os, "chown"): + funcs.append((self.filenames, os.chown, 0, 0)) + if hasattr(os, "lchown"): + funcs.append((self.filenames, os.lchown, 0, 0)) + if hasattr(os, "truncate"): + funcs.append((self.filenames, os.truncate, 0)) if hasattr(os, "chflags"): funcs.extend(( - (os.chflags, 0), - (os.lchflags, 0), + (self.filenames, os.chflags, 0), + (self.filenames, os.lchflags, 0), )) if hasattr(os, "chroot"): - funcs.append((os.chroot,)) + funcs.append((self.filenames, os.chroot,)) if hasattr(os, "link"): - funcs.append((os.link, "dst")) + if sys.platform == "win32": + funcs.append((self.bytes_filenames, os.link, b"dst")) + funcs.append((self.unicode_filenames, os.link, "dst")) + else: + funcs.append((self.filenames, os.link, "dst")) if hasattr(os, "listxattr"): funcs.extend(( - (os.listxattr,), - (os.getxattr, "user.test"), - (os.setxattr, "user.test", b'user'), - (os.removexattr, "user.test"), + (self.filenames, os.listxattr,), + (self.filenames, os.getxattr, "user.test"), + (self.filenames, os.setxattr, "user.test", b'user'), + (self.filenames, os.removexattr, "user.test"), )) if hasattr(os, "lchmod"): - funcs.append((os.lchmod, 0o777)) + funcs.append((self.filenames, os.lchmod, 0o777)) if hasattr(os, "readlink"): - funcs.append((os.readlink,)) + if sys.platform == "win32": + funcs.append((self.unicode_filenames, os.readlink,)) + else: + funcs.append((self.filenames, os.readlink,)) - for func, *func_args in funcs: - for name in self.filenames: + for filenames, func, *func_args in funcs: + for name in filenames: try: func(name, *func_args) except OSError as err: diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1035,17 +1035,6 @@ } static PyObject * -win32_error_unicode(char* function, wchar_t* filename) -{ - /* XXX - see win32_error for comments on 'function' */ - errno = GetLastError(); - if (filename) - return PyErr_SetFromWindowsErrWithUnicodeFilename(errno, filename); - else - return PyErr_SetFromWindowsErr(errno); -} - -static PyObject * win32_error_object(char* function, PyObject* filename) { /* XXX - see win32_error for comments on 'function' */ @@ -1119,44 +1108,6 @@ #ifdef MS_WINDOWS -static PyObject* -win32_1str(PyObject* args, char* func, - char* format, BOOL (__stdcall *funcA)(LPCSTR), - char* wformat, BOOL (__stdcall *funcW)(LPWSTR)) -{ - PyObject *uni; - const char *ansi; - BOOL result; - - if (PyArg_ParseTuple(args, wformat, &uni)) - { - wchar_t *wstr = PyUnicode_AsUnicode(uni); - if (wstr == NULL) - return NULL; - Py_BEGIN_ALLOW_THREADS - result = funcW(wstr); - Py_END_ALLOW_THREADS - if (!result) - return win32_error_object(func, uni); - Py_INCREF(Py_None); - return Py_None; - } - PyErr_Clear(); - - if (!PyArg_ParseTuple(args, format, &ansi)) - return NULL; - if (win32_warn_bytes_api()) - return NULL; - Py_BEGIN_ALLOW_THREADS - result = funcA(ansi); - Py_END_ALLOW_THREADS - if (!result) - return win32_error(func, ansi); - Py_INCREF(Py_None); - return Py_None; - -} - /* This is a reimplementation of the C library's chdir function, but one that produces Win32 errors instead of DOS error codes. chdir is essentially a wrapper around SetCurrentDirectory; however, @@ -2533,7 +2484,7 @@ Py_END_ALLOW_THREADS if (!result) { - return_value = win32_error_object("chmod", path.object); + return_value = path_error(&path); goto exit; } #else /* MS_WINDOWS */ @@ -2989,11 +2940,13 @@ return NULL; } if (!len) { - if (wbuf2 != wbuf) free(wbuf2); - return win32_error("getcwdu", NULL); + if (wbuf2 != wbuf) + free(wbuf2); + return PyErr_SetFromWindowsErr(0); } resobj = PyUnicode_FromWideChar(wbuf2, len); - if (wbuf2 != wbuf) free(wbuf2); + if (wbuf2 != wbuf) + free(wbuf2); return resobj; } @@ -3101,7 +3054,7 @@ Py_END_ALLOW_THREADS if (!result) { - return_value = win32_error_object("link", dst.object); + return_value = path_error(&src); goto exit; } #else @@ -3225,8 +3178,7 @@ if (error == ERROR_FILE_NOT_FOUND) goto exit; Py_DECREF(list); - list = NULL; - win32_error_unicode("FindFirstFileW", wnamebuf); + list = path_error(&path); goto exit; } do { @@ -3255,7 +3207,7 @@ it got to the end of the directory. */ if (!result && GetLastError() != ERROR_NO_MORE_FILES) { Py_DECREF(list); - list = win32_error_unicode("FindNextFileW", wnamebuf); + list = path_error(&path); goto exit; } } while (result == TRUE); @@ -3282,7 +3234,7 @@ if (error == ERROR_FILE_NOT_FOUND) goto exit; Py_DECREF(list); - list = win32_error("FindFirstFile", namebuf); + list = path_error(&path); goto exit; } do { @@ -3310,7 +3262,7 @@ it got to the end of the directory. */ if (!result && GetLastError() != ERROR_NO_MORE_FILES) { Py_DECREF(list); - list = win32_error("FindNextFile", namebuf); + list = path_error(&path); goto exit; } } while (result == TRUE); @@ -3320,7 +3272,7 @@ if (FindClose(hFindFile) == FALSE) { if (list != NULL) { Py_DECREF(list); - list = win32_error_object("FindClose", path.object); + list = path_error(&path); } } } @@ -3569,7 +3521,7 @@ return posix_error(); if (!GetFileInformationByHandle(hFile, &info)) - return win32_error("_getfileinformation", NULL); + return PyErr_SetFromWindowsErr(0); return Py_BuildValue("iii", info.dwVolumeSerialNumber, info.nFileIndexHigh, @@ -3658,7 +3610,7 @@ Py_END_ALLOW_THREADS if (!result) { - return_value = win32_error_object("mkdir", path.object); + return_value = path_error(&path); goto exit; } #else @@ -3828,7 +3780,7 @@ Py_END_ALLOW_THREADS if (!result) { - return_value = win32_error_object(function_name, dst.object); + return_value = path_error(&src); goto exit; } @@ -4396,6 +4348,7 @@ PyObject *return_value = NULL; memset(&path, 0, sizeof(path)); + path.function_name = "utime"; #if UTIME_HAVE_FD path.allow_fd = 1; #endif @@ -4484,7 +4437,7 @@ FILE_FLAG_BACKUP_SEMANTICS, NULL); Py_END_ALLOW_THREADS if (hFile == INVALID_HANDLE_VALUE) { - win32_error_object("utime", path.object); + path_error(&path); goto exit; } @@ -4493,7 +4446,7 @@ GetSystemTime(&now); if (!SystemTimeToFileTime(&now, &mtime) || !SystemTimeToFileTime(&now, &atime)) { - win32_error("utime", NULL); + PyErr_SetFromWindowsErr(0); goto exit; } } @@ -4506,7 +4459,7 @@ as that may confuse the user into believing that something is wrong with the file, when it also could be the time stamp that gives a problem. */ - win32_error("utime", NULL); + PyErr_SetFromWindowsErr(0); goto exit; } #else /* MS_WINDOWS */ @@ -6736,7 +6689,7 @@ Py_END_ALLOW_THREADS if (!result) { - return_value = win32_error_object("symlink", src.object); + return_value = path_error(&src); goto exit; } @@ -6752,7 +6705,7 @@ Py_END_ALLOW_THREADS if (result) { - return_value = path_error(&dst); + return_value = path_error(&src); goto exit; } #endif @@ -7104,12 +7057,6 @@ Py_END_ALLOW_THREADS if (fd == -1) { -#ifdef MS_WINDOWS - /* force use of posix_error here for exact backwards compatibility */ - if (path.wide) - return_value = posix_error(); - else -#endif return_value = path_error(&path); goto exit; } @@ -7648,7 +7595,7 @@ Py_END_ALLOW_THREADS if (res != 0) { #ifdef MS_WINDOWS - return win32_error("fstat", NULL); + return PyErr_SetFromWindowsErr(0); #else return posix_error(); #endif @@ -7694,7 +7641,7 @@ BOOL ok; ok = CreatePipe(&read, &write, NULL, 0); if (!ok) - return win32_error("CreatePipe", NULL); + return PyErr_SetFromWindowsErr(0); read_fd = _open_osfhandle((Py_intptr_t)read, 0); write_fd = _open_osfhandle((Py_intptr_t)write, 1); return Py_BuildValue("(ii)", read_fd, write_fd); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 00:03:39 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Nov 2012 00:03:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogbWVyZ2UgMy4z?= Message-ID: <3XsQ8C2vS9zPj3@mail.python.org> http://hg.python.org/cpython/rev/4ca6f43b12ef changeset: 80145:4ca6f43b12ef parent: 80144:e3eb94389e95 parent: 80143:3c249adc78aa user: Benjamin Peterson date: Wed Oct 31 19:02:30 2012 -0400 summary: merge 3.3 files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 00:49:47 2012 From: python-checkins at python.org (vinay.sajip) Date: Thu, 1 Nov 2012 00:49:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Closes_=2316366=3A_Improve?= =?utf-8?q?_diagnostics_from_handleError=28=29=2E_Thanks_to_Antoine_Pitrou?= Message-ID: <3XsR9R01g7zPNp@mail.python.org> http://hg.python.org/cpython/rev/d7b868cdd9bb changeset: 80146:d7b868cdd9bb user: Vinay Sajip date: Wed Oct 31 23:49:19 2012 +0000 summary: Closes #16366: Improve diagnostics from handleError(). Thanks to Antoine Pitrou for the suggestion. files: Lib/logging/__init__.py | 23 +++++++++++++++++------ 1 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -879,16 +879,27 @@ The record which was being processed is passed in to this method. """ if raiseExceptions and sys.stderr: # see issue 13807 - ei = sys.exc_info() + t, v, tb = sys.exc_info() try: - traceback.print_exception(ei[0], ei[1], ei[2], - None, sys.stderr) - sys.stderr.write('Logged from file %s, line %s\n' % ( - record.filename, record.lineno)) + sys.stderr.write('--- Logging error ---\n') + traceback.print_exception(t, v, tb, None, sys.stderr) + sys.stderr.write('Call stack:\n') + # Walk the stack frame up until we're out of logging, + # so as to print the calling context. + frame = tb.tb_frame + while (frame and os.path.dirname(frame.f_code.co_filename) == + __path__[0]): + frame = frame.f_back + if frame: + traceback.print_stack(frame, file=sys.stderr) + else: + # couldn't find the right stack frame, for some reason + sys.stderr.write('Logged from file %s, line %s\n' % ( + record.filename, record.lineno)) except IOError: #pragma: no cover pass # see issue 5971 finally: - del ei + del t, v, tb class StreamHandler(Handler): """ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 01:26:50 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Nov 2012 01:26:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_point_errors_related_to_no?= =?utf-8?q?nlocals_and_globals_to_the_statement_declaring_them?= Message-ID: <3XsS0B1j7RzPhQ@mail.python.org> http://hg.python.org/cpython/rev/fbfaef0a9c00 changeset: 80147:fbfaef0a9c00 parent: 80145:4ca6f43b12ef user: Benjamin Peterson date: Wed Oct 31 20:26:20 2012 -0400 summary: point errors related to nonlocals and globals to the statement declaring them (closes #10189) files: Include/symtable.h | 1 + Misc/NEWS | 3 + Python/symtable.c | 57 +++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 8 deletions(-) diff --git a/Include/symtable.h b/Include/symtable.h --- a/Include/symtable.h +++ b/Include/symtable.h @@ -39,6 +39,7 @@ PyObject *ste_name; /* string: name of current block */ PyObject *ste_varnames; /* list of function parameters */ PyObject *ste_children; /* list of child blocks */ + PyObject *ste_directives;/* locations of global and nonlocal statements */ _Py_block_ty ste_type; /* module, class, or function */ int ste_unoptimized; /* false if namespace is optimized */ int ste_nested; /* true if block is nested */ diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #10189: Improve the error reporting of SyntaxErrors related to global + and nonlocal statements. + - Issue #16086: PyTypeObject.tp_flags and PyType_Spec.flags are now unsigned (unsigned long and unsigned int) to avoid an undefined behaviour with Py_TPFLAGS_TYPE_SUBCLASS ((1 << 31). PyType_GetFlags() result type is diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -56,6 +56,8 @@ if (ste->ste_children == NULL) goto fail; + ste->ste_directives = NULL; + ste->ste_type = block; ste->ste_unoptimized = 0; ste->ste_nested = 0; @@ -102,6 +104,7 @@ Py_XDECREF(ste->ste_symbols); Py_XDECREF(ste->ste_varnames); Py_XDECREF(ste->ste_children); + Py_XDECREF(ste->ste_directives); PyObject_Del(ste); } @@ -319,6 +322,24 @@ return (PyLong_AS_LONG(v) >> SCOPE_OFFSET) & SCOPE_MASK; } +static int +error_at_directive(PySTEntryObject *ste, PyObject *name) +{ + Py_ssize_t i; + PyObject *data; + assert(ste->ste_directives); + for (i = 0; ; i++) { + data = PyList_GET_ITEM(ste->ste_directives, i); + assert(PyTuple_CheckExact(data)); + if (PyTuple_GET_ITEM(data, 0) == name) + break; + } + PyErr_SyntaxLocationEx(ste->ste_table->st_filename, + PyLong_AsLong(PyTuple_GET_ITEM(data, 1)), + PyLong_AsLong(PyTuple_GET_ITEM(data, 2))); + return 0; +} + /* Analyze raw symbol information to determine scope of each name. @@ -393,16 +414,13 @@ PyErr_Format(PyExc_SyntaxError, "name '%U' is parameter and global", name); - PyErr_SyntaxLocationEx(ste->ste_table->st_filename, - ste->ste_lineno, ste->ste_col_offset); - - return 0; + return error_at_directive(ste, name); } if (flags & DEF_NONLOCAL) { PyErr_Format(PyExc_SyntaxError, "name '%U' is nonlocal and global", name); - return 0; + return error_at_directive(ste, name); } SET_SCOPE(scopes, name, GLOBAL_EXPLICIT); if (PySet_Add(global, name) < 0) @@ -416,19 +434,19 @@ PyErr_Format(PyExc_SyntaxError, "name '%U' is parameter and nonlocal", name); - return 0; + return error_at_directive(ste, name); } if (!bound) { PyErr_Format(PyExc_SyntaxError, "nonlocal declaration not allowed at module level"); - return 0; + return error_at_directive(ste, name); } if (!PySet_Contains(bound, name)) { PyErr_Format(PyExc_SyntaxError, "no binding for nonlocal '%U' found", name); - return 0; + return error_at_directive(ste, name); } SET_SCOPE(scopes, name, FREE); ste->ste_free = 1; @@ -1069,6 +1087,25 @@ static int +symtable_record_directive(struct symtable *st, identifier name, stmt_ty s) +{ + PyObject *data; + int res; + if (!st->st_cur->ste_directives) { + st->st_cur->ste_directives = PyList_New(0); + if (!st->st_cur->ste_directives) + return 0; + } + data = Py_BuildValue("(Oii)", name, s->lineno, s->col_offset); + if (!data) + return 0; + res = PyList_Append(st->st_cur->ste_directives, data); + Py_DECREF(data); + return res == 0; +} + + +static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { switch (s->kind) { @@ -1223,6 +1260,8 @@ } if (!symtable_add_def(st, name, DEF_GLOBAL)) return 0; + if (!symtable_record_directive(st, name, s)) + return 0; } break; } @@ -1252,6 +1291,8 @@ } if (!symtable_add_def(st, name, DEF_NONLOCAL)) return 0; + if (!symtable_record_directive(st, name, s)) + return 0; } break; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 01:26:51 2012 From: python-checkins at python.org (benjamin.peterson) Date: Thu, 1 Nov 2012 01:26:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_merge_heads?= Message-ID: <3XsS0C49dBzPb4@mail.python.org> http://hg.python.org/cpython/rev/2d6eec5d01f7 changeset: 80148:2d6eec5d01f7 parent: 80147:fbfaef0a9c00 parent: 80146:d7b868cdd9bb user: Benjamin Peterson date: Wed Oct 31 20:26:43 2012 -0400 summary: merge heads files: Lib/logging/__init__.py | 23 +++++++++++++++++------ 1 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Lib/logging/__init__.py b/Lib/logging/__init__.py --- a/Lib/logging/__init__.py +++ b/Lib/logging/__init__.py @@ -879,16 +879,27 @@ The record which was being processed is passed in to this method. """ if raiseExceptions and sys.stderr: # see issue 13807 - ei = sys.exc_info() + t, v, tb = sys.exc_info() try: - traceback.print_exception(ei[0], ei[1], ei[2], - None, sys.stderr) - sys.stderr.write('Logged from file %s, line %s\n' % ( - record.filename, record.lineno)) + sys.stderr.write('--- Logging error ---\n') + traceback.print_exception(t, v, tb, None, sys.stderr) + sys.stderr.write('Call stack:\n') + # Walk the stack frame up until we're out of logging, + # so as to print the calling context. + frame = tb.tb_frame + while (frame and os.path.dirname(frame.f_code.co_filename) == + __path__[0]): + frame = frame.f_back + if frame: + traceback.print_stack(frame, file=sys.stderr) + else: + # couldn't find the right stack frame, for some reason + sys.stderr.write('Logged from file %s, line %s\n' % ( + record.filename, record.lineno)) except IOError: #pragma: no cover pass # see issue 5971 finally: - del ei + del t, v, tb class StreamHandler(Handler): """ -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Nov 1 05:56:03 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 01 Nov 2012 05:56:03 +0100 Subject: [Python-checkins] Daily reference leaks (2d6eec5d01f7): sum=2 Message-ID: results for 2d6eec5d01f7 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/reflog9aV4Nv', '-x'] From python-checkins at python.org Thu Nov 1 12:31:59 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 12:31:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE2Mzcz?= =?utf-8?q?=3A_Prevent_infinite_recursion_for_ABC_Set_class_operations=2E?= Message-ID: <3Xsklg0WXwzPw2@mail.python.org> http://hg.python.org/cpython/rev/8e95a078d490 changeset: 80149:8e95a078d490 branch: 3.2 parent: 80133:838e2b19489e user: Andrew Svetlov date: Thu Nov 01 13:28:54 2012 +0200 summary: Issue #16373: Prevent infinite recursion for ABC Set class operations. files: Lib/_abcoll.py | 4 +- Lib/test/test_collections.py | 33 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Lib/_abcoll.py b/Lib/_abcoll.py --- a/Lib/_abcoll.py +++ b/Lib/_abcoll.py @@ -184,12 +184,12 @@ def __gt__(self, other): if not isinstance(other, Set): return NotImplemented - return other < self + return other.__lt__(self) def __ge__(self, other): if not isinstance(other, Set): return NotImplemented - return other <= self + return other.__le__(self) def __eq__(self, other): if not isinstance(other, Set): diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -651,6 +651,39 @@ s |= s self.assertEqual(s, full) + def test_issue16373(self): + # Recursion error comparing comparable and noncomparable + # Set instances + class MyComparableSet(Set): + def __contains__(self, x): + return False + def __len__(self): + return 0 + def __iter__(self): + return iter([]) + class MyNonComparableSet(Set): + def __contains__(self, x): + return False + def __len__(self): + return 0 + def __iter__(self): + return iter([]) + def __le__(self, x): + return NotImplemented + def __lt__(self, x): + return NotImplemented + + cs = MyComparableSet() + ncs = MyNonComparableSet() + with self.assertRaises(TypeError): + ncs < cs + with self.assertRaises(TypeError): + ncs <= cs + with self.assertRaises(TypeError): + cs > ncs + with self.assertRaises(TypeError): + cs >= ncs + def test_Mapping(self): for sample in [dict]: self.assertIsInstance(sample(), Mapping) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 12:32:00 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 12:32:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_issue_=2316373=3A_Prevent_infinite_recursion_for_ABC_Set?= =?utf-8?q?_class_operations=2E?= Message-ID: <3Xsklh38fMzR6Z@mail.python.org> http://hg.python.org/cpython/rev/11a9297733b8 changeset: 80150:11a9297733b8 branch: 3.3 parent: 80143:3c249adc78aa parent: 80149:8e95a078d490 user: Andrew Svetlov date: Thu Nov 01 13:31:12 2012 +0200 summary: Merge issue #16373: Prevent infinite recursion for ABC Set class operations. Patch by Serhiy Storchaka. files: Lib/collections/abc.py | 4 +- Lib/test/test_collections.py | 33 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Lib/collections/abc.py b/Lib/collections/abc.py --- a/Lib/collections/abc.py +++ b/Lib/collections/abc.py @@ -200,12 +200,12 @@ def __gt__(self, other): if not isinstance(other, Set): return NotImplemented - return other < self + return other.__lt__(self) def __ge__(self, other): if not isinstance(other, Set): return NotImplemented - return other <= self + return other.__le__(self) def __eq__(self, other): if not isinstance(other, Set): diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -663,6 +663,39 @@ s |= s self.assertEqual(s, full) + def test_issue16373(self): + # Recursion error comparing comparable and noncomparable + # Set instances + class MyComparableSet(Set): + def __contains__(self, x): + return False + def __len__(self): + return 0 + def __iter__(self): + return iter([]) + class MyNonComparableSet(Set): + def __contains__(self, x): + return False + def __len__(self): + return 0 + def __iter__(self): + return iter([]) + def __le__(self, x): + return NotImplemented + def __lt__(self, x): + return NotImplemented + + cs = MyComparableSet() + ncs = MyNonComparableSet() + with self.assertRaises(TypeError): + ncs < cs + with self.assertRaises(TypeError): + ncs <= cs + with self.assertRaises(TypeError): + cs > ncs + with self.assertRaises(TypeError): + cs >= ncs + def test_Mapping(self): for sample in [dict]: self.assertIsInstance(sample(), Mapping) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 12:32:01 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 12:32:01 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_issue_=2316373=3A_Prevent_infinite_recursion_for_A?= =?utf-8?q?BC_Set_class_operations=2E?= Message-ID: <3Xsklj5Hk3zR9p@mail.python.org> http://hg.python.org/cpython/rev/e67c8803cd82 changeset: 80151:e67c8803cd82 parent: 80148:2d6eec5d01f7 parent: 80150:11a9297733b8 user: Andrew Svetlov date: Thu Nov 01 13:31:31 2012 +0200 summary: Merge issue #16373: Prevent infinite recursion for ABC Set class operations. Patch by Serhiy Storchaka. files: Lib/collections/abc.py | 4 +- Lib/test/test_collections.py | 33 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Lib/collections/abc.py b/Lib/collections/abc.py --- a/Lib/collections/abc.py +++ b/Lib/collections/abc.py @@ -200,12 +200,12 @@ def __gt__(self, other): if not isinstance(other, Set): return NotImplemented - return other < self + return other.__lt__(self) def __ge__(self, other): if not isinstance(other, Set): return NotImplemented - return other <= self + return other.__le__(self) def __eq__(self, other): if not isinstance(other, Set): diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py --- a/Lib/test/test_collections.py +++ b/Lib/test/test_collections.py @@ -663,6 +663,39 @@ s |= s self.assertEqual(s, full) + def test_issue16373(self): + # Recursion error comparing comparable and noncomparable + # Set instances + class MyComparableSet(Set): + def __contains__(self, x): + return False + def __len__(self): + return 0 + def __iter__(self): + return iter([]) + class MyNonComparableSet(Set): + def __contains__(self, x): + return False + def __len__(self): + return 0 + def __iter__(self): + return iter([]) + def __le__(self, x): + return NotImplemented + def __lt__(self, x): + return NotImplemented + + cs = MyComparableSet() + ncs = MyNonComparableSet() + with self.assertRaises(TypeError): + ncs < cs + with self.assertRaises(TypeError): + ncs <= cs + with self.assertRaises(TypeError): + cs > ncs + with self.assertRaises(TypeError): + cs >= ncs + def test_Mapping(self): for sample in [dict]: self.assertIsInstance(sample(), Mapping) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 12:43:53 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 12:43:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Change_docstri?= =?utf-8?q?ng_for_xdrlib=2EError_to_use_new_style_exceptions=2E?= Message-ID: <3Xsl1P5GfDzM5p@mail.python.org> http://hg.python.org/cpython/rev/e95e647040de changeset: 80152:e95e647040de branch: 3.2 parent: 80149:8e95a078d490 user: Andrew Svetlov date: Thu Nov 01 13:43:06 2012 +0200 summary: Change docstring for xdrlib.Error to use new style exceptions. files: Lib/xdrlib.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/xdrlib.py b/Lib/xdrlib.py --- a/Lib/xdrlib.py +++ b/Lib/xdrlib.py @@ -13,7 +13,7 @@ class Error(Exception): """Exception class for this module. Use: - except xdrlib.Error, var: + except xdrlib.Error as var: # var has the Error instance for the exception Public ivars: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 12:43:55 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 12:43:55 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge=3A_change_docstring_for_xdrlib=2EError_to_use_new_style_?= =?utf-8?q?exceptions=2E?= Message-ID: <3Xsl1R0GwgzM5p@mail.python.org> http://hg.python.org/cpython/rev/23ebe277e982 changeset: 80153:23ebe277e982 branch: 3.3 parent: 80150:11a9297733b8 parent: 80152:e95e647040de user: Andrew Svetlov date: Thu Nov 01 13:43:31 2012 +0200 summary: Merge: change docstring for xdrlib.Error to use new style exceptions. files: Lib/xdrlib.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/xdrlib.py b/Lib/xdrlib.py --- a/Lib/xdrlib.py +++ b/Lib/xdrlib.py @@ -13,7 +13,7 @@ class Error(Exception): """Exception class for this module. Use: - except xdrlib.Error, var: + except xdrlib.Error as var: # var has the Error instance for the exception Public ivars: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 12:43:56 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 12:43:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_change_docstring_for_xdrlib=2EError_to_use_new_?= =?utf-8?q?style_exceptions=2E?= Message-ID: <3Xsl1S2n8xzM5p@mail.python.org> http://hg.python.org/cpython/rev/5216c392239a changeset: 80154:5216c392239a parent: 80151:e67c8803cd82 parent: 80153:23ebe277e982 user: Andrew Svetlov date: Thu Nov 01 13:43:43 2012 +0200 summary: Merge: change docstring for xdrlib.Error to use new style exceptions. files: Lib/xdrlib.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/xdrlib.py b/Lib/xdrlib.py --- a/Lib/xdrlib.py +++ b/Lib/xdrlib.py @@ -13,7 +13,7 @@ class Error(Exception): """Exception class for this module. Use: - except xdrlib.Error, var: + except xdrlib.Error as var: # var has the Error instance for the exception Public ivars: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 13:52:16 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 13:52:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE2MjE4?= =?utf-8?q?=3A_Support_non_ascii_characters_in_python_launcher=2E?= Message-ID: <3XsmXJ59rxzR3M@mail.python.org> http://hg.python.org/cpython/rev/02d25098ad57 changeset: 80155:02d25098ad57 branch: 3.3 parent: 80153:23ebe277e982 user: Andrew Svetlov date: Thu Nov 01 14:51:14 2012 +0200 summary: Issue #16218: Support non ascii characters in python launcher. Patch by Serhiy Storchaka. files: Lib/test/test_cmd_line_script.py | 9 +++++++++ Python/pythonrun.c | 9 +++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -363,6 +363,15 @@ self.assertTrue(text[1].startswith(' File ')) self.assertTrue(text[3].startswith('NameError')) + def test_non_utf8(self): + # Issue #16218 + with temp_dir() as script_dir: + script_name = _make_test_script(script_dir, + '\udcf1\udcea\udcf0\udce8\udcef\udcf2') + self._check_script(script_name, script_name, script_name, + script_dir, None, + importlib.machinery.SourceFileLoader) + def test_main(): support.run_unittest(CmdLineTest) support.reap_children() diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1358,16 +1358,21 @@ { PyInterpreterState *interp; PyThreadState *tstate; - PyObject *loader_type, *loader; + PyObject *filename_obj, *loader_type, *loader; int result = 0; + + filename_obj = PyUnicode_DecodeFSDefault(filename); + if (filename_obj == NULL) + return -1; /* Get current thread state and interpreter pointer */ tstate = PyThreadState_GET(); interp = tstate->interp; loader_type = PyObject_GetAttrString(interp->importlib, loader_name); if (loader_type == NULL) { + Py_DECREF(filename_obj); return -1; } - loader = PyObject_CallFunction(loader_type, "ss", "__main__", filename); + loader = PyObject_CallFunction(loader_type, "sN", "__main__", filename_obj); Py_DECREF(loader_type); if (loader == NULL) { return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 13:52:18 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 13:52:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_issue_=2316218=3A_Support_non_ascii_characters_in_?= =?utf-8?q?python_launcher=2E?= Message-ID: <3XsmXL0V4tzNbh@mail.python.org> http://hg.python.org/cpython/rev/1267d64c14b3 changeset: 80156:1267d64c14b3 parent: 80154:5216c392239a parent: 80155:02d25098ad57 user: Andrew Svetlov date: Thu Nov 01 14:52:03 2012 +0200 summary: Merge issue #16218: Support non ascii characters in python launcher. Patch by Serhiy Storchaka. files: Lib/test/test_cmd_line_script.py | 9 +++++++++ Python/pythonrun.c | 9 +++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -363,6 +363,15 @@ self.assertTrue(text[1].startswith(' File ')) self.assertTrue(text[3].startswith('NameError')) + def test_non_utf8(self): + # Issue #16218 + with temp_dir() as script_dir: + script_name = _make_test_script(script_dir, + '\udcf1\udcea\udcf0\udce8\udcef\udcf2') + self._check_script(script_name, script_name, script_name, + script_dir, None, + importlib.machinery.SourceFileLoader) + def test_main(): support.run_unittest(CmdLineTest) support.reap_children() diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1358,16 +1358,21 @@ { PyInterpreterState *interp; PyThreadState *tstate; - PyObject *loader_type, *loader; + PyObject *filename_obj, *loader_type, *loader; int result = 0; + + filename_obj = PyUnicode_DecodeFSDefault(filename); + if (filename_obj == NULL) + return -1; /* Get current thread state and interpreter pointer */ tstate = PyThreadState_GET(); interp = tstate->interp; loader_type = PyObject_GetAttrString(interp->importlib, loader_name); if (loader_type == NULL) { + Py_DECREF(filename_obj); return -1; } - loader = PyObject_CallFunction(loader_type, "ss", "__main__", filename); + loader = PyObject_CallFunction(loader_type, "sN", "__main__", filename_obj); Py_DECREF(loader_type); if (loader == NULL) { return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:04:07 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 1 Nov 2012 20:04:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE2MjI4?= =?utf-8?q?=3A_Fix_a_crash_in_the_json_module_where_a_list_changes_size_wh?= =?utf-8?q?ile_it?= Message-ID: <3XswnM465BzPWM@mail.python.org> http://hg.python.org/cpython/rev/3672db224eb3 changeset: 80157:3672db224eb3 branch: 3.2 parent: 80152:e95e647040de user: Antoine Pitrou date: Thu Nov 01 19:52:06 2012 +0100 summary: Issue #16228: Fix a crash in the json module where a list changes size while it is being encoded. Patch by Serhiy Storchaka. files: Lib/test/json_tests/test_dump.py | 8 ++++++++ Misc/NEWS | 3 +++ Modules/_json.c | 10 +++------- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Lib/test/json_tests/test_dump.py b/Lib/test/json_tests/test_dump.py --- a/Lib/test/json_tests/test_dump.py +++ b/Lib/test/json_tests/test_dump.py @@ -19,6 +19,14 @@ {2: 3.0, 4.0: 5, False: 1, 6: True}, sort_keys=True), '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') + # Issue 16228: Crash on encoding resized list + def test_encode_mutated(self): + a = [object()] * 10 + def crasher(obj): + del a[-1] + self.assertEqual(self.dumps(a, default=crasher), + '[null, null, null, null, null]') + class TestPyDump(TestDump, PyTest): pass class TestCDump(TestDump, CTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,6 +143,9 @@ Library ------- +- Issue #16228: Fix a crash in the json module where a list changes size + while it is being encoded. Patch by Serhiy Storchaka. + - Issue #14897: Enhance error messages of struct.pack and struct.pack_into. Patch by Matti M?ki. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1585,8 +1585,6 @@ static PyObject *empty_array = NULL; PyObject *ident = NULL; PyObject *s_fast = NULL; - Py_ssize_t num_items; - PyObject **seq_items; Py_ssize_t i; if (open_array == NULL || close_array == NULL || empty_array == NULL) { @@ -1600,8 +1598,7 @@ s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence"); if (s_fast == NULL) return -1; - num_items = PySequence_Fast_GET_SIZE(s_fast); - if (num_items == 0) { + if (PySequence_Fast_GET_SIZE(s_fast) == 0) { Py_DECREF(s_fast); return PyList_Append(rval, empty_array); } @@ -1622,7 +1619,6 @@ } } - seq_items = PySequence_Fast_ITEMS(s_fast); if (PyList_Append(rval, open_array)) goto bail; if (s->indent != Py_None) { @@ -1634,8 +1630,8 @@ buf += newline_indent */ } - for (i = 0; i < num_items; i++) { - PyObject *obj = seq_items[i]; + for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) { + PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i); if (i) { if (PyList_Append(rval, s->item_separator)) goto bail; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:04:08 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 1 Nov 2012 20:04:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2316228=3A_Fix_a_crash_in_the_json_module_where_a_list_?= =?utf-8?q?changes_size_while_it?= Message-ID: <3XswnN6ZVQzPkt@mail.python.org> http://hg.python.org/cpython/rev/7528c02b8d52 changeset: 80158:7528c02b8d52 branch: 3.3 parent: 80155:02d25098ad57 parent: 80157:3672db224eb3 user: Antoine Pitrou date: Thu Nov 01 19:59:21 2012 +0100 summary: Issue #16228: Fix a crash in the json module where a list changes size while it is being encoded. Patch by Serhiy Storchaka. files: Lib/test/json_tests/test_dump.py | 8 ++++++++ Misc/NEWS | 3 +++ Modules/_json.c | 10 +++------- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Lib/test/json_tests/test_dump.py b/Lib/test/json_tests/test_dump.py --- a/Lib/test/json_tests/test_dump.py +++ b/Lib/test/json_tests/test_dump.py @@ -20,6 +20,14 @@ {2: 3.0, 4.0: 5, False: 1, 6: True}, sort_keys=True), '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') + # Issue 16228: Crash on encoding resized list + def test_encode_mutated(self): + a = [object()] * 10 + def crasher(obj): + del a[-1] + self.assertEqual(self.dumps(a, default=crasher), + '[null, null, null, null, null]') + class TestPyDump(TestDump, PyTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,9 @@ Library ------- +- Issue #16228: Fix a crash in the json module where a list changes size + while it is being encoded. Patch by Serhiy Storchaka. + - Issue #14897: Enhance error messages of struct.pack and struct.pack_into. Patch by Matti M?ki. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1660,8 +1660,6 @@ static PyObject *empty_array = NULL; PyObject *ident = NULL; PyObject *s_fast = NULL; - Py_ssize_t num_items; - PyObject **seq_items; Py_ssize_t i; if (open_array == NULL || close_array == NULL || empty_array == NULL) { @@ -1675,8 +1673,7 @@ s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence"); if (s_fast == NULL) return -1; - num_items = PySequence_Fast_GET_SIZE(s_fast); - if (num_items == 0) { + if (PySequence_Fast_GET_SIZE(s_fast) == 0) { Py_DECREF(s_fast); return _PyAccu_Accumulate(acc, empty_array); } @@ -1697,7 +1694,6 @@ } } - seq_items = PySequence_Fast_ITEMS(s_fast); if (_PyAccu_Accumulate(acc, open_array)) goto bail; if (s->indent != Py_None) { @@ -1709,8 +1705,8 @@ buf += newline_indent */ } - for (i = 0; i < num_items; i++) { - PyObject *obj = seq_items[i]; + for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) { + PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i); if (i) { if (_PyAccu_Accumulate(acc, s->item_separator)) goto bail; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:04:10 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 1 Nov 2012 20:04:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316228=3A_Fix_a_crash_in_the_json_module_where_a?= =?utf-8?q?_list_changes_size_while_it?= Message-ID: <3XswnQ1g6KzPyK@mail.python.org> http://hg.python.org/cpython/rev/ab65509b8443 changeset: 80159:ab65509b8443 parent: 80156:1267d64c14b3 parent: 80158:7528c02b8d52 user: Antoine Pitrou date: Thu Nov 01 20:03:30 2012 +0100 summary: Issue #16228: Fix a crash in the json module where a list changes size while it is being encoded. Patch by Serhiy Storchaka. files: Lib/test/json_tests/test_dump.py | 8 ++++++++ Misc/NEWS | 3 +++ Modules/_json.c | 10 +++------- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Lib/test/json_tests/test_dump.py b/Lib/test/json_tests/test_dump.py --- a/Lib/test/json_tests/test_dump.py +++ b/Lib/test/json_tests/test_dump.py @@ -20,6 +20,14 @@ {2: 3.0, 4.0: 5, False: 1, 6: True}, sort_keys=True), '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') + # Issue 16228: Crash on encoding resized list + def test_encode_mutated(self): + a = [object()] * 10 + def crasher(obj): + del a[-1] + self.assertEqual(self.dumps(a, default=crasher), + '[null, null, null, null, null]') + class TestPyDump(TestDump, PyTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -85,6 +85,9 @@ Library ------- +- Issue #16228: Fix a crash in the json module where a list changes size + while it is being encoded. Patch by Serhiy Storchaka. + - Issue #16351: New function gc.get_stats() returns per-generation collection statistics. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -1659,8 +1659,6 @@ static PyObject *empty_array = NULL; PyObject *ident = NULL; PyObject *s_fast = NULL; - Py_ssize_t num_items; - PyObject **seq_items; Py_ssize_t i; if (open_array == NULL || close_array == NULL || empty_array == NULL) { @@ -1674,8 +1672,7 @@ s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence"); if (s_fast == NULL) return -1; - num_items = PySequence_Fast_GET_SIZE(s_fast); - if (num_items == 0) { + if (PySequence_Fast_GET_SIZE(s_fast) == 0) { Py_DECREF(s_fast); return _PyAccu_Accumulate(acc, empty_array); } @@ -1696,7 +1693,6 @@ } } - seq_items = PySequence_Fast_ITEMS(s_fast); if (_PyAccu_Accumulate(acc, open_array)) goto bail; if (s->indent != Py_None) { @@ -1708,8 +1704,8 @@ buf += newline_indent */ } - for (i = 0; i < num_items; i++) { - PyObject *obj = seq_items[i]; + for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) { + PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i); if (i) { if (_PyAccu_Accumulate(acc, s->item_separator)) goto bail; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:08:21 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 1 Nov 2012 20:08:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2MjI4?= =?utf-8?q?=3A_Fix_a_crash_in_the_json_module_where_a_list_changes_size_wh?= =?utf-8?q?ile_it?= Message-ID: <3XswtF095yzQkG@mail.python.org> http://hg.python.org/cpython/rev/33ae62a4ecf5 changeset: 80160:33ae62a4ecf5 branch: 2.7 parent: 80136:8296b686c6de user: Antoine Pitrou date: Thu Nov 01 20:07:40 2012 +0100 summary: Issue #16228: Fix a crash in the json module where a list changes size while it is being encoded. Patch by Serhiy Storchaka. files: Lib/json/tests/test_dump.py | 9 +++++++++ Misc/NEWS | 3 +++ Modules/_json.c | 10 +++------- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Lib/json/tests/test_dump.py b/Lib/json/tests/test_dump.py --- a/Lib/json/tests/test_dump.py +++ b/Lib/json/tests/test_dump.py @@ -19,5 +19,14 @@ {2: 3.0, 4.0: 5L, False: 1, 6L: True}, sort_keys=True), '{"false": 1, "2": 3.0, "4.0": 5, "6": true}') + # Issue 16228: Crash on encoding resized list + def test_encode_mutated(self): + a = [object()] * 10 + def crasher(obj): + del a[-1] + self.assertEqual(self.dumps(a, default=crasher), + '[null, null, null, null, null]') + + class TestPyDump(TestDump, PyTest): pass class TestCDump(TestDump, CTest): pass diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -130,6 +130,9 @@ Library ------- +- Issue #16228: Fix a crash in the json module where a list changes size + while it is being encoded. Patch by Serhiy Storchaka. + - Issue #14897: Enhance error messages of struct.pack and struct.pack_into. Patch by Matti M?ki. diff --git a/Modules/_json.c b/Modules/_json.c --- a/Modules/_json.c +++ b/Modules/_json.c @@ -2224,8 +2224,6 @@ static PyObject *empty_array = NULL; PyObject *ident = NULL; PyObject *s_fast = NULL; - Py_ssize_t num_items; - PyObject **seq_items; Py_ssize_t i; if (open_array == NULL || close_array == NULL || empty_array == NULL) { @@ -2239,8 +2237,7 @@ s_fast = PySequence_Fast(seq, "_iterencode_list needs a sequence"); if (s_fast == NULL) return -1; - num_items = PySequence_Fast_GET_SIZE(s_fast); - if (num_items == 0) { + if (PySequence_Fast_GET_SIZE(s_fast) == 0) { Py_DECREF(s_fast); return PyList_Append(rval, empty_array); } @@ -2261,7 +2258,6 @@ } } - seq_items = PySequence_Fast_ITEMS(s_fast); if (PyList_Append(rval, open_array)) goto bail; if (s->indent != Py_None) { @@ -2273,8 +2269,8 @@ buf += newline_indent */ } - for (i = 0; i < num_items; i++) { - PyObject *obj = seq_items[i]; + for (i = 0; i < PySequence_Fast_GET_SIZE(s_fast); i++) { + PyObject *obj = PySequence_Fast_GET_ITEM(s_fast, i); if (i) { if (PyList_Append(rval, s->item_separator)) goto bail; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:20:33 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 1 Nov 2012 20:20:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE2MjMw?= =?utf-8?q?=3A_Fix_a_crash_in_select=2Eselect=28=29_when_one_the_lists_cha?= =?utf-8?q?nges_size?= Message-ID: <3Xsx8K56d3zNJQ@mail.python.org> http://hg.python.org/cpython/rev/87ccf2635ad7 changeset: 80161:87ccf2635ad7 branch: 3.2 parent: 80157:3672db224eb3 user: Antoine Pitrou date: Thu Nov 01 20:13:54 2012 +0100 summary: Issue #16230: Fix a crash in select.select() when one the lists changes size while iterated on. Patch by Serhiy Storchaka. files: Lib/test/test_select.py | 10 ++++++++++ Misc/NEWS | 3 +++ Modules/selectmodule.c | 6 ++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -49,6 +49,16 @@ self.fail('Unexpected return values from select():', rfd, wfd, xfd) p.close() + # Issue 16230: Crash on select resized list + def test_select_mutated(self): + a = [] + class F: + def fileno(self): + del a[-1] + return sys.__stdout__.fileno() + a[:] = [F()] * 10 + self.assertEqual(select.select([], a, []), ([], a[:5], [])) + def test_main(): support.run_unittest(SelectTestCase) support.reap_children() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,6 +143,9 @@ Library ------- +- Issue #16230: Fix a crash in select.select() when one the lists changes + size while iterated on. Patch by Serhiy Storchaka. + - Issue #16228: Fix a crash in the json module where a list changes size while it is being encoded. Patch by Serhiy Storchaka. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -83,7 +83,7 @@ { int max = -1; int index = 0; - Py_ssize_t i, len = -1; + Py_ssize_t i; PyObject* fast_seq = NULL; PyObject* o = NULL; @@ -94,9 +94,7 @@ if (!fast_seq) return -1; - len = PySequence_Fast_GET_SIZE(fast_seq); - - for (i = 0; i < len; i++) { + for (i = 0; i < PySequence_Fast_GET_SIZE(fast_seq); i++) { SOCKET v; /* any intervening fileno() calls could decr this refcnt */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:20:35 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 1 Nov 2012 20:20:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2316230=3A_Fix_a_crash_in_select=2Eselect=28=29_when_on?= =?utf-8?q?e_the_lists_changes_size?= Message-ID: <3Xsx8M0XdrzPlS@mail.python.org> http://hg.python.org/cpython/rev/717660ec8f67 changeset: 80162:717660ec8f67 branch: 3.3 parent: 80158:7528c02b8d52 parent: 80161:87ccf2635ad7 user: Antoine Pitrou date: Thu Nov 01 20:15:23 2012 +0100 summary: Issue #16230: Fix a crash in select.select() when one the lists changes size while iterated on. Patch by Serhiy Storchaka. files: Lib/test/test_select.py | 10 ++++++++++ Misc/NEWS | 3 +++ Modules/selectmodule.c | 6 ++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -65,6 +65,16 @@ self.fail('Unexpected return values from select():', rfd, wfd, xfd) p.close() + # Issue 16230: Crash on select resized list + def test_select_mutated(self): + a = [] + class F: + def fileno(self): + del a[-1] + return sys.__stdout__.fileno() + a[:] = [F()] * 10 + self.assertEqual(select.select([], a, []), ([], a[:5], [])) + def test_main(): support.run_unittest(SelectTestCase) support.reap_children() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,9 @@ Library ------- +- Issue #16230: Fix a crash in select.select() when one the lists changes + size while iterated on. Patch by Serhiy Storchaka. + - Issue #16228: Fix a crash in the json module where a list changes size while it is being encoded. Patch by Serhiy Storchaka. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -89,7 +89,7 @@ { int max = -1; int index = 0; - Py_ssize_t i, len = -1; + Py_ssize_t i; PyObject* fast_seq = NULL; PyObject* o = NULL; @@ -100,9 +100,7 @@ if (!fast_seq) return -1; - len = PySequence_Fast_GET_SIZE(fast_seq); - - for (i = 0; i < len; i++) { + for (i = 0; i < PySequence_Fast_GET_SIZE(fast_seq); i++) { SOCKET v; /* any intervening fileno() calls could decr this refcnt */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:20:36 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 1 Nov 2012 20:20:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316230=3A_Fix_a_crash_in_select=2Eselect=28=29_w?= =?utf-8?q?hen_one_the_lists_changes_size?= Message-ID: <3Xsx8N2gwGzPwh@mail.python.org> http://hg.python.org/cpython/rev/823898ef37ce changeset: 80163:823898ef37ce parent: 80159:ab65509b8443 parent: 80162:717660ec8f67 user: Antoine Pitrou date: Thu Nov 01 20:16:07 2012 +0100 summary: Issue #16230: Fix a crash in select.select() when one the lists changes size while iterated on. Patch by Serhiy Storchaka. files: Lib/test/test_select.py | 10 ++++++++++ Misc/NEWS | 3 +++ Modules/selectmodule.c | 6 ++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -65,6 +65,16 @@ self.fail('Unexpected return values from select():', rfd, wfd, xfd) p.close() + # Issue 16230: Crash on select resized list + def test_select_mutated(self): + a = [] + class F: + def fileno(self): + del a[-1] + return sys.__stdout__.fileno() + a[:] = [F()] * 10 + self.assertEqual(select.select([], a, []), ([], a[:5], [])) + def test_main(): support.run_unittest(SelectTestCase) support.reap_children() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -85,6 +85,9 @@ Library ------- +- Issue #16230: Fix a crash in select.select() when one the lists changes + size while iterated on. Patch by Serhiy Storchaka. + - Issue #16228: Fix a crash in the json module where a list changes size while it is being encoded. Patch by Serhiy Storchaka. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -84,7 +84,7 @@ { int max = -1; int index = 0; - Py_ssize_t i, len = -1; + Py_ssize_t i; PyObject* fast_seq = NULL; PyObject* o = NULL; @@ -95,9 +95,7 @@ if (!fast_seq) return -1; - len = PySequence_Fast_GET_SIZE(fast_seq); - - for (i = 0; i < len; i++) { + for (i = 0; i < PySequence_Fast_GET_SIZE(fast_seq); i++) { SOCKET v; /* any intervening fileno() calls could decr this refcnt */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:20:37 2012 From: python-checkins at python.org (antoine.pitrou) Date: Thu, 1 Nov 2012 20:20:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2MjMw?= =?utf-8?q?=3A_Fix_a_crash_in_select=2Eselect=28=29_when_one_the_lists_cha?= =?utf-8?q?nges_size?= Message-ID: <3Xsx8P54SPzPyB@mail.python.org> http://hg.python.org/cpython/rev/02a5322b0cee changeset: 80164:02a5322b0cee branch: 2.7 parent: 80160:33ae62a4ecf5 user: Antoine Pitrou date: Thu Nov 01 20:13:54 2012 +0100 summary: Issue #16230: Fix a crash in select.select() when one the lists changes size while iterated on. Patch by Serhiy Storchaka. files: Lib/test/test_select.py | 9 +++++++++ Misc/NEWS | 3 +++ Modules/selectmodule.c | 5 +---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_select.py b/Lib/test/test_select.py --- a/Lib/test/test_select.py +++ b/Lib/test/test_select.py @@ -49,6 +49,15 @@ self.fail('Unexpected return values from select():', rfd, wfd, xfd) p.close() + # Issue 16230: Crash on select resized list + def test_select_mutated(self): + a = [] + class F: + def fileno(self): + del a[-1] + return sys.__stdout__.fileno() + a[:] = [F()] * 10 + self.assertEqual(select.select([], a, []), ([], a[:5], [])) def test_main(): test_support.run_unittest(SelectTestCase) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -130,6 +130,9 @@ Library ------- +- Issue #16230: Fix a crash in select.select() when one the lists changes + size while iterated on. Patch by Serhiy Storchaka. + - Issue #16228: Fix a crash in the json module where a list changes size while it is being encoded. Patch by Serhiy Storchaka. diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -87,7 +87,6 @@ int i; int max = -1; int index = 0; - int len = -1; PyObject* fast_seq = NULL; PyObject* o = NULL; @@ -98,9 +97,7 @@ if (!fast_seq) return -1; - len = PySequence_Fast_GET_SIZE(fast_seq); - - for (i = 0; i < len; i++) { + for (i = 0; i < PySequence_Fast_GET_SIZE(fast_seq); i++) { SOCKET v; /* any intervening fileno() calls could decr this refcnt */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:28:51 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 20:28:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE0ODkz?= =?utf-8?q?=3A_Add_function_annotation_example_to_function_tutorial=2E?= Message-ID: <3XsxKv69jbzPb8@mail.python.org> http://hg.python.org/cpython/rev/2bf99322218f changeset: 80165:2bf99322218f branch: 3.2 parent: 80161:87ccf2635ad7 user: Andrew Svetlov date: Thu Nov 01 21:26:55 2012 +0200 summary: Issue #14893: Add function annotation example to function tutorial. Patch by Zachary Ware. files: Doc/tutorial/controlflow.rst | 34 ++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -656,6 +656,40 @@ No, really, it doesn't do anything. +.. _tut-annotations: + +Function Annotations +-------------------- + +.. sectionauthor:: Zachary Ware +.. index:: + pair: function; annotations + single: -> (return annotation assignment) + +:ref:`Function annotations ` are completely optional, +arbitrary metadata information about user-defined functions. Neither Python +itself nor the standard library use function annotations in any way; this +section just shows the syntax. Third-party projects are free to use function +annotations for documentation, type checking, and other uses. + +Annotations are stored in the :attr:`__annotations__` attribute of the function +as a dictionary and have no effect on any other part of the function. Parameter +annotations are defined by a colon after the parameter name, followed by an +expression evaluating to the value of the annotation. Return annotations are +defined by a literal ``->``, followed by an expression, between the parameter +list and the colon denoting the end of the :keyword:`def` statement. The +following example has a positional argument, a keyword argument, and the return +value annotated with nonsense:: + + >>> def f(ham: 42, eggs: int = 'spam') -> "Nothing to see here": + ... print("Annotations:", f.__annotations__) + ... print("Arguments:", ham, eggs) + ... + >>> f('wonderful') + Annotations: {'eggs': , 'return': 'Nothing to see here', 'ham': 42} + Arguments: wonderful spam + + .. _tut-codingstyle: Intermezzo: Coding Style -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:28:53 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 20:28:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_issue_=2314893=3A_Add_function_annotation_example_to_fun?= =?utf-8?q?ction_tutorial=2E?= Message-ID: <3XsxKx1cSNzPyB@mail.python.org> http://hg.python.org/cpython/rev/45167091b5f9 changeset: 80166:45167091b5f9 branch: 3.3 parent: 80162:717660ec8f67 parent: 80165:2bf99322218f user: Andrew Svetlov date: Thu Nov 01 21:27:23 2012 +0200 summary: Merge issue #14893: Add function annotation example to function tutorial. Patch by Zachary Ware. files: Doc/tutorial/controlflow.rst | 34 ++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -656,6 +656,40 @@ No, really, it doesn't do anything. +.. _tut-annotations: + +Function Annotations +-------------------- + +.. sectionauthor:: Zachary Ware +.. index:: + pair: function; annotations + single: -> (return annotation assignment) + +:ref:`Function annotations ` are completely optional, +arbitrary metadata information about user-defined functions. Neither Python +itself nor the standard library use function annotations in any way; this +section just shows the syntax. Third-party projects are free to use function +annotations for documentation, type checking, and other uses. + +Annotations are stored in the :attr:`__annotations__` attribute of the function +as a dictionary and have no effect on any other part of the function. Parameter +annotations are defined by a colon after the parameter name, followed by an +expression evaluating to the value of the annotation. Return annotations are +defined by a literal ``->``, followed by an expression, between the parameter +list and the colon denoting the end of the :keyword:`def` statement. The +following example has a positional argument, a keyword argument, and the return +value annotated with nonsense:: + + >>> def f(ham: 42, eggs: int = 'spam') -> "Nothing to see here": + ... print("Annotations:", f.__annotations__) + ... print("Arguments:", ham, eggs) + ... + >>> f('wonderful') + Annotations: {'eggs': , 'return': 'Nothing to see here', 'ham': 42} + Arguments: wonderful spam + + .. _tut-codingstyle: Intermezzo: Coding Style -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:28:54 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 20:28:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_issue_=2314893=3A_Add_function_annotation_example_?= =?utf-8?q?to_function_tutorial=2E?= Message-ID: <3XsxKy3yHJzPyB@mail.python.org> http://hg.python.org/cpython/rev/63b495ff366b changeset: 80167:63b495ff366b parent: 80163:823898ef37ce parent: 80166:45167091b5f9 user: Andrew Svetlov date: Thu Nov 01 21:28:40 2012 +0200 summary: Merge issue #14893: Add function annotation example to function tutorial. Patch by Zachary Ware. files: Doc/tutorial/controlflow.rst | 34 ++++++++++++++++++++++++ 1 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -656,6 +656,40 @@ No, really, it doesn't do anything. +.. _tut-annotations: + +Function Annotations +-------------------- + +.. sectionauthor:: Zachary Ware +.. index:: + pair: function; annotations + single: -> (return annotation assignment) + +:ref:`Function annotations ` are completely optional, +arbitrary metadata information about user-defined functions. Neither Python +itself nor the standard library use function annotations in any way; this +section just shows the syntax. Third-party projects are free to use function +annotations for documentation, type checking, and other uses. + +Annotations are stored in the :attr:`__annotations__` attribute of the function +as a dictionary and have no effect on any other part of the function. Parameter +annotations are defined by a colon after the parameter name, followed by an +expression evaluating to the value of the annotation. Return annotations are +defined by a literal ``->``, followed by an expression, between the parameter +list and the colon denoting the end of the :keyword:`def` statement. The +following example has a positional argument, a keyword argument, and the return +value annotated with nonsense:: + + >>> def f(ham: 42, eggs: int = 'spam') -> "Nothing to see here": + ... print("Annotations:", f.__annotations__) + ... print("Arguments:", ham, eggs) + ... + >>> f('wonderful') + Annotations: {'eggs': , 'return': 'Nothing to see here', 'ham': 42} + Arguments: wonderful spam + + .. _tut-codingstyle: Intermezzo: Coding Style -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:48:44 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 20:48:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Reword_set_doc?= =?utf-8?q?s_to_use_*proper_subset/superset*_terminology=2E?= Message-ID: <3Xsxmr5P5XzPlS@mail.python.org> http://hg.python.org/cpython/rev/7dda9dc5e830 changeset: 80168:7dda9dc5e830 branch: 2.7 parent: 80164:02a5322b0cee user: Andrew Svetlov date: Thu Nov 01 21:47:05 2012 +0200 summary: Reword set docs to use *proper subset/superset* terminology. files: Doc/library/stdtypes.rst | 4 ++-- 1 files changed, 2 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 @@ -1771,7 +1771,7 @@ .. method:: set < other - Test whether the set is a true subset of *other*, that is, + Test whether the set is a proper subset of *other*, that is, ``set <= other and set != other``. .. method:: issuperset(other) @@ -1781,7 +1781,7 @@ .. method:: set > other - Test whether the set is a true superset of *other*, that is, ``set >= + Test whether the set is a proper superset of *other*, that is, ``set >= other and set != other``. .. method:: union(other, ...) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:48:46 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 20:48:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Reword_set_doc?= =?utf-8?q?s_to_use_*proper_subset/superset*_terminology=2E?= Message-ID: <3Xsxmt0mMqzPnk@mail.python.org> http://hg.python.org/cpython/rev/fa7311caa203 changeset: 80169:fa7311caa203 branch: 3.2 parent: 80165:2bf99322218f user: Andrew Svetlov date: Thu Nov 01 21:47:54 2012 +0200 summary: Reword set docs to use *proper subset/superset* terminology. files: Doc/library/stdtypes.rst | 4 ++-- 1 files changed, 2 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 @@ -1954,7 +1954,7 @@ .. method:: set < other - Test whether the set is a true subset of *other*, that is, + Test whether the set is a proper subset of *other*, that is, ``set <= other and set != other``. .. method:: issuperset(other) @@ -1964,7 +1964,7 @@ .. method:: set > other - Test whether the set is a true superset of *other*, that is, ``set >= + Test whether the set is a proper superset of *other*, that is, ``set >= other and set != other``. .. method:: union(other, ...) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:48:47 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 20:48:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge=3A_Reword_set_docs_to_use_*proper_subset/superset*_termi?= =?utf-8?q?nology=2E?= Message-ID: <3Xsxmv2xvYzPtf@mail.python.org> http://hg.python.org/cpython/rev/95a4c7d02309 changeset: 80170:95a4c7d02309 branch: 3.3 parent: 80166:45167091b5f9 parent: 80169:fa7311caa203 user: Andrew Svetlov date: Thu Nov 01 21:48:16 2012 +0200 summary: Merge: Reword set docs to use *proper subset/superset* terminology. files: Doc/library/stdtypes.rst | 4 ++-- 1 files changed, 2 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 @@ -2793,7 +2793,7 @@ .. method:: set < other - Test whether the set is a true subset of *other*, that is, + Test whether the set is a proper subset of *other*, that is, ``set <= other and set != other``. .. method:: issuperset(other) @@ -2803,7 +2803,7 @@ .. method:: set > other - Test whether the set is a true superset of *other*, that is, ``set >= + Test whether the set is a proper superset of *other*, that is, ``set >= other and set != other``. .. method:: union(other, ...) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 20:48:48 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 20:48:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge=3A_Reword_set_docs_to_use_*proper_subset/superset*?= =?utf-8?q?_terminology=2E?= Message-ID: <3Xsxmw56JtzPtj@mail.python.org> http://hg.python.org/cpython/rev/56c3ab6f7f07 changeset: 80171:56c3ab6f7f07 parent: 80167:63b495ff366b parent: 80170:95a4c7d02309 user: Andrew Svetlov date: Thu Nov 01 21:48:34 2012 +0200 summary: Merge: Reword set docs to use *proper subset/superset* terminology. files: Doc/library/stdtypes.rst | 4 ++-- 1 files changed, 2 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 @@ -2793,7 +2793,7 @@ .. method:: set < other - Test whether the set is a true subset of *other*, that is, + Test whether the set is a proper subset of *other*, that is, ``set <= other and set != other``. .. method:: issuperset(other) @@ -2803,7 +2803,7 @@ .. method:: set > other - Test whether the set is a true superset of *other*, that is, ``set >= + Test whether the set is a proper superset of *other*, that is, ``set >= other and set != other``. .. method:: union(other, ...) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 21:44:59 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 21:44:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzEyMDc1?= =?utf-8?q?89=3A_Add_Cut/Copy/Paste_items_to_IDLE_right_click_Context_Menu?= Message-ID: <3Xsz1l1vxfzMXv@mail.python.org> http://hg.python.org/cpython/rev/639dd6e62de4 changeset: 80172:639dd6e62de4 branch: 2.7 parent: 80168:7dda9dc5e830 user: Andrew Svetlov date: Thu Nov 01 22:39:14 2012 +0200 summary: Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu Patch by Todd Rovito. files: Doc/library/idle.rst | 21 ++++++++++++ Lib/idlelib/EditorWindow.py | 42 ++++++++++++++++++++---- Lib/idlelib/OutputWindow.py | 6 ++- Lib/idlelib/PyShell.py | 22 +++++++++++- Lib/idlelib/help.txt | 15 +++++++- Misc/NEWS | 3 + 6 files changed, 96 insertions(+), 13 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -183,6 +183,15 @@ * Right-click in Edit window (Control-click on OS X) +Cut + Copy selection into system-wide clipboard; then delete selection + +Copy + Copy selection into system-wide clipboard + +Paste + Insert system-wide clipboard into window + Set Breakpoint Sets a breakpoint. Breakpoints are only enabled when the debugger is open. @@ -190,6 +199,9 @@ Clears the breakpoint on that line. .. index:: + single: Cut + single: Copy + single: Paste single: Set Breakpoint single: Clear Breakpoint single: breakpoints @@ -200,6 +212,15 @@ * Right-click in Python Shell window (Control-click on OS X) +Cut + Copy selection into system-wide clipboard; then delete selection + +Copy + Copy selection into system-wide clipboard + +Paste + Insert system-wide clipboard into window + Go to file/line Same as in Debug menu. diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -470,7 +470,6 @@ rmenu = None def right_menu_event(self, event): - self.text.tag_remove("sel", "1.0", "end") self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) if not self.rmenu: self.make_rmenu() @@ -479,23 +478,52 @@ iswin = sys.platform[:3] == 'win' if iswin: self.text.config(cursor="arrow") + + for label, eventname, verify_state in self.rmenu_specs: + if verify_state is None: + continue + state = getattr(self, verify_state)() + rmenu.entryconfigure(label, state=state) + rmenu.tk_popup(event.x_root, event.y_root) if iswin: self.text.config(cursor="ibeam") rmenu_specs = [ - # ("Label", "<>"), ... - ("Close", "<>"), # Example + # ("Label", "<>", "statefuncname"), ... + ("Close", "<>", None), # Example ] def make_rmenu(self): rmenu = Menu(self.text, tearoff=0) - for label, eventname in self.rmenu_specs: - def command(text=self.text, eventname=eventname): - text.event_generate(eventname) - rmenu.add_command(label=label, command=command) + for label, eventname, _ in self.rmenu_specs: + if label is not None: + def command(text=self.text, eventname=eventname): + text.event_generate(eventname) + rmenu.add_command(label=label, command=command) + else: + rmenu.add_separator() self.rmenu = rmenu + def rmenu_check_cut(self): + return self.rmenu_check_copy() + + def rmenu_check_copy(self): + try: + indx = self.text.index('sel.first') + except TclError: + return 'disabled' + else: + return 'normal' if indx else 'disabled' + + def rmenu_check_paste(self): + try: + self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD') + except TclError: + return 'disabled' + else: + return 'normal' + def about_dialog(self, event=None): aboutDialog.AboutDialog(self.top,'About IDLE') diff --git a/Lib/idlelib/OutputWindow.py b/Lib/idlelib/OutputWindow.py --- a/Lib/idlelib/OutputWindow.py +++ b/Lib/idlelib/OutputWindow.py @@ -57,7 +57,11 @@ # Our own right-button menu rmenu_specs = [ - ("Go to file/line", "<>"), + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + (None, None, None), + ("Go to file/line", "<>", None), ] file_line_pats = [ diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -122,8 +122,13 @@ old_hook() self.io.set_filename_change_hook(filename_changed_hook) - rmenu_specs = [("Set Breakpoint", "<>"), - ("Clear Breakpoint", "<>")] + rmenu_specs = [ + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + ("Set Breakpoint", "<>", None), + ("Clear Breakpoint", "<>", None) + ] def set_breakpoint(self, lineno): text = self.text @@ -1261,6 +1266,19 @@ if not use_subprocess: raise KeyboardInterrupt + def rmenu_check_cut(self): + try: + if self.text.compare('sel.first', '<', 'iomark'): + return 'disabled' + except TclError: # no selection, so the index 'sel.first' doesn't exist + return 'disabled' + return super(PyShell, self).rmenu_check_cut() + + def rmenu_check_paste(self): + if self.text.compare('insert', '<', 'iomark'): + return 'disabled' + return super(PyShell, self).rmenu_check_paste() + class PseudoFile(object): def __init__(self, shell, tags, encoding=None): diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -120,14 +120,23 @@ --- (Additional Help Sources may be added here) -Edit context menu (Right-click / Control-click in Edit window): +Edit context menu (Right-click / Control-click on OS X in Edit window): + Cut -- Copy a selection into system-wide clipboard, + then delete the selection + Copy -- Copy selection into system-wide clipboard + Paste -- Insert system-wide clipboard into window Set Breakpoint -- Sets a breakpoint (when debugger open) Clear Breakpoint -- Clears the breakpoint on that line -Shell context menu (Right-click / Control-click in Shell window): +Shell context menu (Right-click / Control-click on OS X in Shell window): - Go to file/line -- Same as in Debug menu + Cut -- Copy a selection into system-wide clipboard, + then delete the selection + Copy -- Copy selection into system-wide clipboard + Paste -- Insert system-wide clipboard into window + --- + Go to file/line -- Same as in Debug menu ** TIPS ** diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -130,6 +130,9 @@ Library ------- +- Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu + Patch by Todd Rovito. + - Issue #16230: Fix a crash in select.select() when one the lists changes size while iterated on. Patch by Serhiy Storchaka. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 21:45:00 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 21:45:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzEyMDc1?= =?utf-8?q?89=3A_Add_Cut/Copy/Paste_items_to_IDLE_right_click_Context_Menu?= Message-ID: <3Xsz1m5jHtzPs3@mail.python.org> http://hg.python.org/cpython/rev/66643fcf6ee9 changeset: 80173:66643fcf6ee9 branch: 3.2 parent: 80169:fa7311caa203 user: Andrew Svetlov date: Thu Nov 01 22:41:19 2012 +0200 summary: Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu Patch by Todd Rovito. files: Doc/library/idle.rst | 21 ++++++++++++ Lib/idlelib/EditorWindow.py | 43 ++++++++++++++++++++---- Lib/idlelib/OutputWindow.py | 6 ++- Lib/idlelib/PyShell.py | 23 ++++++++++++- Lib/idlelib/help.txt | 15 ++++++- Misc/NEWS | 3 + 6 files changed, 98 insertions(+), 13 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -183,6 +183,15 @@ * Right-click in Edit window (Control-click on OS X) +Cut + Copy selection into system-wide clipboard; then delete selection + +Copy + Copy selection into system-wide clipboard + +Paste + Insert system-wide clipboard into window + Set Breakpoint Sets a breakpoint. Breakpoints are only enabled when the debugger is open. @@ -190,6 +199,9 @@ Clears the breakpoint on that line. .. index:: + single: Cut + single: Copy + single: Paste single: Set Breakpoint single: Clear Breakpoint single: breakpoints @@ -200,6 +212,15 @@ * Right-click in Python Shell window (Control-click on OS X) +Cut + Copy selection into system-wide clipboard; then delete selection + +Copy + Copy selection into system-wide clipboard + +Paste + Insert system-wide clipboard into window + Go to file/line Same as in Debug menu. diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -464,7 +464,6 @@ rmenu = None def right_menu_event(self, event): - self.text.tag_remove("sel", "1.0", "end") self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) if not self.rmenu: self.make_rmenu() @@ -473,23 +472,53 @@ iswin = sys.platform[:3] == 'win' if iswin: self.text.config(cursor="arrow") + + for label, eventname, verify_state in self.rmenu_specs: + if verify_state is None: + continue + state = getattr(self, verify_state)() + rmenu.entryconfigure(label, state=state) + + rmenu.tk_popup(event.x_root, event.y_root) if iswin: self.text.config(cursor="ibeam") rmenu_specs = [ - # ("Label", "<>"), ... - ("Close", "<>"), # Example + # ("Label", "<>", "statefuncname"), ... + ("Close", "<>", None), # Example ] def make_rmenu(self): rmenu = Menu(self.text, tearoff=0) - for label, eventname in self.rmenu_specs: - def command(text=self.text, eventname=eventname): - text.event_generate(eventname) - rmenu.add_command(label=label, command=command) + for label, eventname, _ in self.rmenu_specs: + if label is not None: + def command(text=self.text, eventname=eventname): + text.event_generate(eventname) + rmenu.add_command(label=label, command=command) + else: + rmenu.add_separator() self.rmenu = rmenu + def rmenu_check_cut(self): + return self.rmenu_check_copy() + + def rmenu_check_copy(self): + try: + indx = self.text.index('sel.first') + except TclError: + return 'disabled' + else: + return 'normal' if indx else 'disabled' + + def rmenu_check_paste(self): + try: + self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD') + except TclError: + return 'disabled' + else: + return 'normal' + def about_dialog(self, event=None): aboutDialog.AboutDialog(self.top,'About IDLE') diff --git a/Lib/idlelib/OutputWindow.py b/Lib/idlelib/OutputWindow.py --- a/Lib/idlelib/OutputWindow.py +++ b/Lib/idlelib/OutputWindow.py @@ -52,7 +52,11 @@ # Our own right-button menu rmenu_specs = [ - ("Go to file/line", "<>"), + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + (None, None, None), + ("Go to file/line", "<>", None), ] file_line_pats = [ diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -117,8 +117,14 @@ old_hook() self.io.set_filename_change_hook(filename_changed_hook) - rmenu_specs = [("Set Breakpoint", "<>"), - ("Clear Breakpoint", "<>")] + rmenu_specs = [ + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + (None, None, None), + ("Set Breakpoint", "<>", None), + ("Clear Breakpoint", "<>", None) + ] def set_breakpoint(self, lineno): text = self.text @@ -1240,6 +1246,19 @@ raise KeyboardInterrupt return count + def rmenu_check_cut(self): + try: + if self.text.compare('sel.first', '<', 'iomark'): + return 'disabled' + except TclError: # no selection, so the index 'sel.first' doesn't exist + return 'disabled' + return super().rmenu_check_cut() + + def rmenu_check_paste(self): + if self.text.compare('insert','<','iomark'): + return 'disabled' + return super().rmenu_check_paste() + class PseudoFile(object): def __init__(self, shell, tags, encoding=None): diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -120,14 +120,23 @@ --- (Additional Help Sources may be added here) -Edit context menu (Right-click / Control-click in Edit window): +Edit context menu (Right-click / Control-click on OS X in Edit window): + Cut -- Copy a selection into system-wide clipboard, + then delete the selection + Copy -- Copy selection into system-wide clipboard + Paste -- Insert system-wide clipboard into window Set Breakpoint -- Sets a breakpoint (when debugger open) Clear Breakpoint -- Clears the breakpoint on that line -Shell context menu (Right-click / Control-click in Shell window): +Shell context menu (Right-click / Control-click on OS X in Shell window): - Go to file/line -- Same as in Debug menu + Cut -- Copy a selection into system-wide clipboard, + then delete the selection + Copy -- Copy selection into system-wide clipboard + Paste -- Insert system-wide clipboard into window + --- + Go to file/line -- Same as in Debug menu ** TIPS ** diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,6 +143,9 @@ Library ------- +- Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu + Patch by Todd Rovito. + - Issue #16230: Fix a crash in select.select() when one the lists changes size while iterated on. Patch by Serhiy Storchaka. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 21:45:02 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 21:45:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_issue_=231207589=3A_Add_Cut/Copy/Paste_items_to_IDLE_rig?= =?utf-8?q?ht_click_Context_Menu?= Message-ID: <3Xsz1p21nlzPxB@mail.python.org> http://hg.python.org/cpython/rev/3f3b72ab9d65 changeset: 80174:3f3b72ab9d65 branch: 3.3 parent: 80170:95a4c7d02309 parent: 80173:66643fcf6ee9 user: Andrew Svetlov date: Thu Nov 01 22:44:06 2012 +0200 summary: Merge issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu Patch by Todd Rovito. files: Doc/library/idle.rst | 21 ++++++++++++ Lib/idlelib/EditorWindow.py | 43 ++++++++++++++++++++---- Lib/idlelib/OutputWindow.py | 6 ++- Lib/idlelib/PyShell.py | 23 ++++++++++++- Lib/idlelib/help.txt | 15 ++++++- Misc/NEWS | 3 + 6 files changed, 98 insertions(+), 13 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -183,6 +183,15 @@ * Right-click in Edit window (Control-click on OS X) +Cut + Copy selection into system-wide clipboard; then delete selection + +Copy + Copy selection into system-wide clipboard + +Paste + Insert system-wide clipboard into window + Set Breakpoint Sets a breakpoint. Breakpoints are only enabled when the debugger is open. @@ -190,6 +199,9 @@ Clears the breakpoint on that line. .. index:: + single: Cut + single: Copy + single: Paste single: Set Breakpoint single: Clear Breakpoint single: breakpoints @@ -200,6 +212,15 @@ * Right-click in Python Shell window (Control-click on OS X) +Cut + Copy selection into system-wide clipboard; then delete selection + +Copy + Copy selection into system-wide clipboard + +Paste + Insert system-wide clipboard into window + Go to file/line Same as in Debug menu. diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -464,7 +464,6 @@ rmenu = None def right_menu_event(self, event): - self.text.tag_remove("sel", "1.0", "end") self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) if not self.rmenu: self.make_rmenu() @@ -473,23 +472,53 @@ iswin = sys.platform[:3] == 'win' if iswin: self.text.config(cursor="arrow") + + for label, eventname, verify_state in self.rmenu_specs: + if verify_state is None: + continue + state = getattr(self, verify_state)() + rmenu.entryconfigure(label, state=state) + + rmenu.tk_popup(event.x_root, event.y_root) if iswin: self.text.config(cursor="ibeam") rmenu_specs = [ - # ("Label", "<>"), ... - ("Close", "<>"), # Example + # ("Label", "<>", "statefuncname"), ... + ("Close", "<>", None), # Example ] def make_rmenu(self): rmenu = Menu(self.text, tearoff=0) - for label, eventname in self.rmenu_specs: - def command(text=self.text, eventname=eventname): - text.event_generate(eventname) - rmenu.add_command(label=label, command=command) + for label, eventname, _ in self.rmenu_specs: + if label is not None: + def command(text=self.text, eventname=eventname): + text.event_generate(eventname) + rmenu.add_command(label=label, command=command) + else: + rmenu.add_separator() self.rmenu = rmenu + def rmenu_check_cut(self): + return self.rmenu_check_copy() + + def rmenu_check_copy(self): + try: + indx = self.text.index('sel.first') + except TclError: + return 'disabled' + else: + return 'normal' if indx else 'disabled' + + def rmenu_check_paste(self): + try: + self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD') + except TclError: + return 'disabled' + else: + return 'normal' + def about_dialog(self, event=None): aboutDialog.AboutDialog(self.top,'About IDLE') diff --git a/Lib/idlelib/OutputWindow.py b/Lib/idlelib/OutputWindow.py --- a/Lib/idlelib/OutputWindow.py +++ b/Lib/idlelib/OutputWindow.py @@ -52,7 +52,11 @@ # Our own right-button menu rmenu_specs = [ - ("Go to file/line", "<>"), + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + (None, None, None), + ("Go to file/line", "<>", None), ] file_line_pats = [ diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -117,8 +117,14 @@ old_hook() self.io.set_filename_change_hook(filename_changed_hook) - rmenu_specs = [("Set Breakpoint", "<>"), - ("Clear Breakpoint", "<>")] + rmenu_specs = [ + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + (None, None, None), + ("Set Breakpoint", "<>", None), + ("Clear Breakpoint", "<>", None) + ] def set_breakpoint(self, lineno): text = self.text @@ -1256,6 +1262,19 @@ raise KeyboardInterrupt return count + def rmenu_check_cut(self): + try: + if self.text.compare('sel.first', '<', 'iomark'): + return 'disabled' + except TclError: # no selection, so the index 'sel.first' doesn't exist + return 'disabled' + return super().rmenu_check_cut() + + def rmenu_check_paste(self): + if self.text.compare('insert','<','iomark'): + return 'disabled' + return super().rmenu_check_paste() + class PseudoFile(object): def __init__(self, shell, tags, encoding=None): diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -120,14 +120,23 @@ --- (Additional Help Sources may be added here) -Edit context menu (Right-click / Control-click in Edit window): +Edit context menu (Right-click / Control-click on OS X in Edit window): + Cut -- Copy a selection into system-wide clipboard, + then delete the selection + Copy -- Copy selection into system-wide clipboard + Paste -- Insert system-wide clipboard into window Set Breakpoint -- Sets a breakpoint (when debugger open) Clear Breakpoint -- Clears the breakpoint on that line -Shell context menu (Right-click / Control-click in Shell window): +Shell context menu (Right-click / Control-click on OS X in Shell window): - Go to file/line -- Same as in Debug menu + Cut -- Copy a selection into system-wide clipboard, + then delete the selection + Copy -- Copy selection into system-wide clipboard + Paste -- Insert system-wide clipboard into window + --- + Go to file/line -- Same as in Debug menu ** TIPS ** diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,9 @@ Library ------- +- Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu + Patch by Todd Rovito. + - Issue #16230: Fix a crash in select.select() when one the lists changes size while iterated on. Patch by Serhiy Storchaka. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 1 21:45:03 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 1 Nov 2012 21:45:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_issue_=231207589=3A_Add_Cut/Copy/Paste_items_to_ID?= =?utf-8?q?LE_right_click_Context_Menu?= Message-ID: <3Xsz1q5cdWzQsw@mail.python.org> http://hg.python.org/cpython/rev/e6bf779111a8 changeset: 80175:e6bf779111a8 parent: 80171:56c3ab6f7f07 parent: 80174:3f3b72ab9d65 user: Andrew Svetlov date: Thu Nov 01 22:44:45 2012 +0200 summary: Merge issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu Patch by Todd Rovito. files: Doc/library/idle.rst | 21 ++++++++++++ Lib/idlelib/EditorWindow.py | 43 ++++++++++++++++++++---- Lib/idlelib/OutputWindow.py | 6 ++- Lib/idlelib/PyShell.py | 23 ++++++++++++- Lib/idlelib/help.txt | 15 ++++++- Misc/NEWS | 3 + 6 files changed, 98 insertions(+), 13 deletions(-) diff --git a/Doc/library/idle.rst b/Doc/library/idle.rst --- a/Doc/library/idle.rst +++ b/Doc/library/idle.rst @@ -183,6 +183,15 @@ * Right-click in Edit window (Control-click on OS X) +Cut + Copy selection into system-wide clipboard; then delete selection + +Copy + Copy selection into system-wide clipboard + +Paste + Insert system-wide clipboard into window + Set Breakpoint Sets a breakpoint. Breakpoints are only enabled when the debugger is open. @@ -190,6 +199,9 @@ Clears the breakpoint on that line. .. index:: + single: Cut + single: Copy + single: Paste single: Set Breakpoint single: Clear Breakpoint single: breakpoints @@ -200,6 +212,15 @@ * Right-click in Python Shell window (Control-click on OS X) +Cut + Copy selection into system-wide clipboard; then delete selection + +Copy + Copy selection into system-wide clipboard + +Paste + Insert system-wide clipboard into window + Go to file/line Same as in Debug menu. diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -464,7 +464,6 @@ rmenu = None def right_menu_event(self, event): - self.text.tag_remove("sel", "1.0", "end") self.text.mark_set("insert", "@%d,%d" % (event.x, event.y)) if not self.rmenu: self.make_rmenu() @@ -473,23 +472,53 @@ iswin = sys.platform[:3] == 'win' if iswin: self.text.config(cursor="arrow") + + for label, eventname, verify_state in self.rmenu_specs: + if verify_state is None: + continue + state = getattr(self, verify_state)() + rmenu.entryconfigure(label, state=state) + + rmenu.tk_popup(event.x_root, event.y_root) if iswin: self.text.config(cursor="ibeam") rmenu_specs = [ - # ("Label", "<>"), ... - ("Close", "<>"), # Example + # ("Label", "<>", "statefuncname"), ... + ("Close", "<>", None), # Example ] def make_rmenu(self): rmenu = Menu(self.text, tearoff=0) - for label, eventname in self.rmenu_specs: - def command(text=self.text, eventname=eventname): - text.event_generate(eventname) - rmenu.add_command(label=label, command=command) + for label, eventname, _ in self.rmenu_specs: + if label is not None: + def command(text=self.text, eventname=eventname): + text.event_generate(eventname) + rmenu.add_command(label=label, command=command) + else: + rmenu.add_separator() self.rmenu = rmenu + def rmenu_check_cut(self): + return self.rmenu_check_copy() + + def rmenu_check_copy(self): + try: + indx = self.text.index('sel.first') + except TclError: + return 'disabled' + else: + return 'normal' if indx else 'disabled' + + def rmenu_check_paste(self): + try: + self.text.tk.call('tk::GetSelection', self.text, 'CLIPBOARD') + except TclError: + return 'disabled' + else: + return 'normal' + def about_dialog(self, event=None): aboutDialog.AboutDialog(self.top,'About IDLE') diff --git a/Lib/idlelib/OutputWindow.py b/Lib/idlelib/OutputWindow.py --- a/Lib/idlelib/OutputWindow.py +++ b/Lib/idlelib/OutputWindow.py @@ -52,7 +52,11 @@ # Our own right-button menu rmenu_specs = [ - ("Go to file/line", "<>"), + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + (None, None, None), + ("Go to file/line", "<>", None), ] file_line_pats = [ diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -117,8 +117,14 @@ old_hook() self.io.set_filename_change_hook(filename_changed_hook) - rmenu_specs = [("Set Breakpoint", "<>"), - ("Clear Breakpoint", "<>")] + rmenu_specs = [ + ("Cut", "<>", "rmenu_check_cut"), + ("Copy", "<>", "rmenu_check_copy"), + ("Paste", "<>", "rmenu_check_paste"), + (None, None, None), + ("Set Breakpoint", "<>", None), + ("Clear Breakpoint", "<>", None) + ] def set_breakpoint(self, lineno): text = self.text @@ -1259,6 +1265,19 @@ raise KeyboardInterrupt return count + def rmenu_check_cut(self): + try: + if self.text.compare('sel.first', '<', 'iomark'): + return 'disabled' + except TclError: # no selection, so the index 'sel.first' doesn't exist + return 'disabled' + return super().rmenu_check_cut() + + def rmenu_check_paste(self): + if self.text.compare('insert','<','iomark'): + return 'disabled' + return super().rmenu_check_paste() + class PseudoFile(object): def __init__(self, shell, tags, encoding=None): diff --git a/Lib/idlelib/help.txt b/Lib/idlelib/help.txt --- a/Lib/idlelib/help.txt +++ b/Lib/idlelib/help.txt @@ -120,14 +120,23 @@ --- (Additional Help Sources may be added here) -Edit context menu (Right-click / Control-click in Edit window): +Edit context menu (Right-click / Control-click on OS X in Edit window): + Cut -- Copy a selection into system-wide clipboard, + then delete the selection + Copy -- Copy selection into system-wide clipboard + Paste -- Insert system-wide clipboard into window Set Breakpoint -- Sets a breakpoint (when debugger open) Clear Breakpoint -- Clears the breakpoint on that line -Shell context menu (Right-click / Control-click in Shell window): +Shell context menu (Right-click / Control-click on OS X in Shell window): - Go to file/line -- Same as in Debug menu + Cut -- Copy a selection into system-wide clipboard, + then delete the selection + Copy -- Copy selection into system-wide clipboard + Paste -- Insert system-wide clipboard into window + --- + Go to file/line -- Same as in Debug menu ** TIPS ** diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -85,6 +85,9 @@ Library ------- +- Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu + Patch by Todd Rovito. + - Issue #16230: Fix a crash in select.select() when one the lists changes size while iterated on. Patch by Serhiy Storchaka. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 02:17:13 2012 From: python-checkins at python.org (chris.jerdonek) Date: Fri, 2 Nov 2012 02:17:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?devguide=3A_Clarify_the_behavior_of_t?= =?utf-8?q?he_=22builtin=22_index_directive_entry_type=2E?= Message-ID: <3Xt53s5GcFzMjH@mail.python.org> http://hg.python.org/devguide/rev/fbbfd430f9c1 changeset: 562:fbbfd430f9c1 user: Chris Jerdonek date: Thu Nov 01 18:16:30 2012 -0700 summary: Clarify the behavior of the "builtin" index directive entry type. files: documenting.rst | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/documenting.rst b/documenting.rst --- a/documenting.rst +++ b/documenting.rst @@ -1339,8 +1339,10 @@ index entries, which are ``module; search path``, ``search; path, module`` and ``path; module search``. module, keyword, operator, object, exception, statement, builtin - These all create two index entries. For example, ``module: hashlib`` creates - the entries ``module; hashlib`` and ``hashlib; module``. + These all create two index entries. For example, ``module: hashlib`` + creates the entries ``module; hashlib`` and ``hashlib; module``. The + builtin entry type is slightly different in that "built-in function" is used + in place of "builtin" when creating the two entries. For index directives containing only "single" entries, there is a shorthand notation:: -- Repository URL: http://hg.python.org/devguide From solipsis at pitrou.net Fri Nov 2 05:54:11 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Fri, 02 Nov 2012 05:54:11 +0100 Subject: [Python-checkins] Daily reference leaks (e6bf779111a8): sum=0 Message-ID: results for e6bf779111a8 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog9WAKAc', '-x'] From python-checkins at python.org Fri Nov 2 07:33:31 2012 From: python-checkins at python.org (georg.brandl) Date: Fri, 2 Nov 2012 07:33:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Grammar_touchu?= =?utf-8?q?p=2E?= Message-ID: <3XtD4q1gMzzPwT@mail.python.org> http://hg.python.org/cpython/rev/cf62fbf2171a changeset: 80176:cf62fbf2171a branch: 3.2 parent: 80173:66643fcf6ee9 user: Georg Brandl date: Fri Nov 02 07:34:37 2012 +0100 summary: Grammar touchup. files: Doc/extending/embedding.rst | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Doc/extending/embedding.rst b/Doc/extending/embedding.rst --- a/Doc/extending/embedding.rst +++ b/Doc/extending/embedding.rst @@ -66,18 +66,16 @@ return 0; } -Function :c:func:`Py_SetProgramName` should be called before -:c:func:`Py_Initialize` to inform the interpreter about paths to -Python run-time libraries. Next initialize the Python interpreter -with :c:func:`Py_Initialize`, followed by the execution of a -hard-coded Python script that prints the date and time. Afterwards, -the :c:func:`Py_Finalize` call shuts the interpreter down, followed by -the end of the program. In a real program, you may want to get the -Python script from another source, perhaps a text-editor routine, a -file, or a database. Getting the Python code from a file can better -be done by using the :c:func:`PyRun_SimpleFile` function, which saves -you the trouble of allocating memory space and loading the file -contents. +The :c:func:`Py_SetProgramName` function should be called before +:c:func:`Py_Initialize` to inform the interpreter about paths to Python run-time +libraries. Next, the Python interpreter is initialized with +:c:func:`Py_Initialize`, followed by the execution of a hard-coded Python script +that prints the date and time. Afterwards, the :c:func:`Py_Finalize` call shuts +the interpreter down, followed by the end of the program. In a real program, +you may want to get the Python script from another source, perhaps a text-editor +routine, a file, or a database. Getting the Python code from a file can better +be done by using the :c:func:`PyRun_SimpleFile` function, which saves you the +trouble of allocating memory space and loading the file contents. .. _lower-level-embedding: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 07:33:32 2012 From: python-checkins at python.org (georg.brandl) Date: Fri, 2 Nov 2012 07:33:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_merge_with_3=2E2?= Message-ID: <3XtD4r47jrzRDX@mail.python.org> http://hg.python.org/cpython/rev/e33bc12fcde1 changeset: 80177:e33bc12fcde1 branch: 3.3 parent: 80174:3f3b72ab9d65 parent: 80176:cf62fbf2171a user: Georg Brandl date: Fri Nov 02 07:34:46 2012 +0100 summary: merge with 3.2 files: Doc/extending/embedding.rst | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Doc/extending/embedding.rst b/Doc/extending/embedding.rst --- a/Doc/extending/embedding.rst +++ b/Doc/extending/embedding.rst @@ -66,18 +66,16 @@ return 0; } -Function :c:func:`Py_SetProgramName` should be called before -:c:func:`Py_Initialize` to inform the interpreter about paths to -Python run-time libraries. Next initialize the Python interpreter -with :c:func:`Py_Initialize`, followed by the execution of a -hard-coded Python script that prints the date and time. Afterwards, -the :c:func:`Py_Finalize` call shuts the interpreter down, followed by -the end of the program. In a real program, you may want to get the -Python script from another source, perhaps a text-editor routine, a -file, or a database. Getting the Python code from a file can better -be done by using the :c:func:`PyRun_SimpleFile` function, which saves -you the trouble of allocating memory space and loading the file -contents. +The :c:func:`Py_SetProgramName` function should be called before +:c:func:`Py_Initialize` to inform the interpreter about paths to Python run-time +libraries. Next, the Python interpreter is initialized with +:c:func:`Py_Initialize`, followed by the execution of a hard-coded Python script +that prints the date and time. Afterwards, the :c:func:`Py_Finalize` call shuts +the interpreter down, followed by the end of the program. In a real program, +you may want to get the Python script from another source, perhaps a text-editor +routine, a file, or a database. Getting the Python code from a file can better +be done by using the :c:func:`PyRun_SimpleFile` function, which saves you the +trouble of allocating memory space and loading the file contents. .. _lower-level-embedding: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 07:33:33 2012 From: python-checkins at python.org (georg.brandl) Date: Fri, 2 Nov 2012 07:33:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_merge_with_3=2E3?= Message-ID: <3XtD4s6CxRzRCf@mail.python.org> http://hg.python.org/cpython/rev/58ee0c60d6bf changeset: 80178:58ee0c60d6bf parent: 80175:e6bf779111a8 parent: 80177:e33bc12fcde1 user: Georg Brandl date: Fri Nov 02 07:34:52 2012 +0100 summary: merge with 3.3 files: Doc/extending/embedding.rst | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Doc/extending/embedding.rst b/Doc/extending/embedding.rst --- a/Doc/extending/embedding.rst +++ b/Doc/extending/embedding.rst @@ -66,18 +66,16 @@ return 0; } -Function :c:func:`Py_SetProgramName` should be called before -:c:func:`Py_Initialize` to inform the interpreter about paths to -Python run-time libraries. Next initialize the Python interpreter -with :c:func:`Py_Initialize`, followed by the execution of a -hard-coded Python script that prints the date and time. Afterwards, -the :c:func:`Py_Finalize` call shuts the interpreter down, followed by -the end of the program. In a real program, you may want to get the -Python script from another source, perhaps a text-editor routine, a -file, or a database. Getting the Python code from a file can better -be done by using the :c:func:`PyRun_SimpleFile` function, which saves -you the trouble of allocating memory space and loading the file -contents. +The :c:func:`Py_SetProgramName` function should be called before +:c:func:`Py_Initialize` to inform the interpreter about paths to Python run-time +libraries. Next, the Python interpreter is initialized with +:c:func:`Py_Initialize`, followed by the execution of a hard-coded Python script +that prints the date and time. Afterwards, the :c:func:`Py_Finalize` call shuts +the interpreter down, followed by the end of the program. In a real program, +you may want to get the Python script from another source, perhaps a text-editor +routine, a file, or a database. Getting the Python code from a file can better +be done by using the :c:func:`PyRun_SimpleFile` function, which saves you the +trouble of allocating memory space and loading the file contents. .. _lower-level-embedding: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 07:33:56 2012 From: python-checkins at python.org (georg.brandl) Date: Fri, 2 Nov 2012 07:33:56 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Grammar_touchu?= =?utf-8?q?p=2E?= Message-ID: <3XtD5J3GzMzRDg@mail.python.org> http://hg.python.org/cpython/rev/466cbfb3c0c6 changeset: 80179:466cbfb3c0c6 branch: 2.7 parent: 80172:639dd6e62de4 user: Georg Brandl date: Fri Nov 02 07:34:37 2012 +0100 summary: Grammar touchup. files: Doc/extending/embedding.rst | 22 ++++++++++------------ 1 files changed, 10 insertions(+), 12 deletions(-) diff --git a/Doc/extending/embedding.rst b/Doc/extending/embedding.rst --- a/Doc/extending/embedding.rst +++ b/Doc/extending/embedding.rst @@ -69,18 +69,16 @@ return 0; } -Function :c:func:`Py_SetProgramName` should be called before -:c:func:`Py_Initialize` to inform the interpreter about paths to -Python run-time libraries. Next initialize the Python interpreter -with :c:func:`Py_Initialize`, followed by the execution of a -hard-coded Python script that prints the date and time. Afterwards, -the :c:func:`Py_Finalize` call shuts the interpreter down, followed by -the end of the program. In a real program, you may want to get the -Python script from another source, perhaps a text-editor routine, a -file, or a database. Getting the Python code from a file can better -be done by using the :c:func:`PyRun_SimpleFile` function, which saves -you the trouble of allocating memory space and loading the file -contents. +The :c:func:`Py_SetProgramName` function should be called before +:c:func:`Py_Initialize` to inform the interpreter about paths to Python run-time +libraries. Next, the Python interpreter is initialized with +:c:func:`Py_Initialize`, followed by the execution of a hard-coded Python script +that prints the date and time. Afterwards, the :c:func:`Py_Finalize` call shuts +the interpreter down, followed by the end of the program. In a real program, +you may want to get the Python script from another source, perhaps a text-editor +routine, a file, or a database. Getting the Python code from a file can better +be done by using the :c:func:`PyRun_SimpleFile` function, which saves you the +trouble of allocating memory space and loading the file contents. .. _lower-level-embedding: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 15:01:44 2012 From: python-checkins at python.org (stefan.krah) Date: Fri, 2 Nov 2012 15:01:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE2MTQ1?= =?utf-8?q?=3A_Support_legacy_strings_in_the_=5Fcsv_module=2E?= Message-ID: <3XtQ203lcCzRGd@mail.python.org> http://hg.python.org/cpython/rev/0b5f00ccf907 changeset: 80180:0b5f00ccf907 branch: 3.3 parent: 80177:e33bc12fcde1 user: Stefan Krah date: Fri Nov 02 14:44:20 2012 +0100 summary: Issue #16145: Support legacy strings in the _csv module. files: Lib/test/test_csv.py | 11 +++++++++++ Modules/_csv.c | 21 +++++++++++++++------ Modules/_testcapimodule.c | 24 ++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -197,6 +197,17 @@ fileobj.seek(0) self.assertEqual(fileobj.read(), "a,b\r\nc,d\r\n") + @support.cpython_only + def test_writerows_legacy_strings(self): + import _testcapi + + c = _testcapi.unicode_legacy_string('a') + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([[c]]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), "a\r\n") + def _read_test(self, input, expect, **kwargs): reader = csv.reader(input, **kwargs) result = list(reader) diff --git a/Modules/_csv.c b/Modules/_csv.c --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -13,8 +13,6 @@ #include "Python.h" #include "structmember.h" -#define IS_BASESTRING(o) \ - PyUnicode_Check(o) typedef struct { PyObject *error_obj; /* CSV exception */ @@ -248,6 +246,7 @@ name); return -1; } + /* PyUnicode_READY() is called in PyUnicode_GetLength() */ if (len > 0) *target = PyUnicode_READ_CHAR(src, 0); } @@ -263,12 +262,14 @@ else { if (src == Py_None) *target = NULL; - else if (!IS_BASESTRING(src)) { + else if (!PyUnicode_Check(src)) { PyErr_Format(PyExc_TypeError, "\"%s\" must be a string", name); return -1; } else { + if (PyUnicode_READY(src) == -1) + return -1; Py_XDECREF(*target); Py_INCREF(src); *target = src; @@ -357,7 +358,7 @@ return NULL; if (dialect != NULL) { - if (IS_BASESTRING(dialect)) { + if (PyUnicode_Check(dialect)) { dialect = get_dialect_from_registry(dialect); if (dialect == NULL) return NULL; @@ -808,6 +809,10 @@ Py_DECREF(lineobj); return NULL; } + if (PyUnicode_READY(lineobj) == -1) { + Py_DECREF(lineobj); + return NULL; + } ++self->line_num; kind = PyUnicode_KIND(lineobj); data = PyUnicode_DATA(lineobj); @@ -1108,6 +1113,8 @@ Py_ssize_t rec_len; if (field != NULL) { + if (PyUnicode_READY(field) == -1) + return 0; field_kind = PyUnicode_KIND(field); field_data = PyUnicode_DATA(field); field_len = PyUnicode_GET_LENGTH(field); @@ -1403,11 +1410,13 @@ if (!PyArg_UnpackTuple(args, "", 1, 2, &name_obj, &dialect_obj)) return NULL; - if (!IS_BASESTRING(name_obj)) { + if (!PyUnicode_Check(name_obj)) { PyErr_SetString(PyExc_TypeError, - "dialect name must be a string or unicode"); + "dialect name must be a string"); return NULL; } + if (PyUnicode_READY(name_obj) == -1) + return NULL; dialect = _call_dialect(dialect_obj, kwargs); if (dialect == NULL) return NULL; diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1521,6 +1521,29 @@ } static PyObject * +unicode_legacy_string(PyObject *self, PyObject *args) +{ + Py_UNICODE *data; + Py_ssize_t len; + PyObject *u; + + if (!PyArg_ParseTuple(args, "u#", &data, &len)) + return NULL; + + u = PyUnicode_FromUnicode(NULL, len); + if (u == NULL) + return NULL; + + memcpy(PyUnicode_AS_UNICODE(u), data, len * sizeof(Py_UNICODE)); + + if (len > 0) { /* The empty string is always ready. */ + assert(!PyUnicode_IS_READY(u)); + } + + return u; +} + +static PyObject * getargs_w_star(PyObject *self, PyObject *args) { Py_buffer buffer; @@ -2506,6 +2529,7 @@ {"unicode_aswidecharstring",unicode_aswidecharstring, METH_VARARGS}, {"unicode_encodedecimal", unicode_encodedecimal, METH_VARARGS}, {"unicode_transformdecimaltoascii", unicode_transformdecimaltoascii, METH_VARARGS}, + {"unicode_legacy_string", unicode_legacy_string, METH_VARARGS}, #ifdef WITH_THREAD {"_test_thread_state", test_thread_state, METH_VARARGS}, {"_pending_threadfunc", pending_threadfunc, METH_VARARGS}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 15:01:46 2012 From: python-checkins at python.org (stefan.krah) Date: Fri, 2 Nov 2012 15:01:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4zLg==?= Message-ID: <3XtQ2205TszRJy@mail.python.org> http://hg.python.org/cpython/rev/f1a25c088b8f changeset: 80181:f1a25c088b8f parent: 80178:58ee0c60d6bf parent: 80180:0b5f00ccf907 user: Stefan Krah date: Fri Nov 02 14:49:02 2012 +0100 summary: Merge 3.3. files: Lib/test/test_csv.py | 11 +++++++++++ Modules/_csv.c | 21 +++++++++++++++------ Modules/_testcapimodule.c | 24 ++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_csv.py b/Lib/test/test_csv.py --- a/Lib/test/test_csv.py +++ b/Lib/test/test_csv.py @@ -197,6 +197,17 @@ fileobj.seek(0) self.assertEqual(fileobj.read(), "a,b\r\nc,d\r\n") + @support.cpython_only + def test_writerows_legacy_strings(self): + import _testcapi + + c = _testcapi.unicode_legacy_string('a') + with TemporaryFile("w+", newline='') as fileobj: + writer = csv.writer(fileobj) + writer.writerows([[c]]) + fileobj.seek(0) + self.assertEqual(fileobj.read(), "a\r\n") + def _read_test(self, input, expect, **kwargs): reader = csv.reader(input, **kwargs) result = list(reader) diff --git a/Modules/_csv.c b/Modules/_csv.c --- a/Modules/_csv.c +++ b/Modules/_csv.c @@ -13,8 +13,6 @@ #include "Python.h" #include "structmember.h" -#define IS_BASESTRING(o) \ - PyUnicode_Check(o) typedef struct { PyObject *error_obj; /* CSV exception */ @@ -248,6 +246,7 @@ name); return -1; } + /* PyUnicode_READY() is called in PyUnicode_GetLength() */ if (len > 0) *target = PyUnicode_READ_CHAR(src, 0); } @@ -263,12 +262,14 @@ else { if (src == Py_None) *target = NULL; - else if (!IS_BASESTRING(src)) { + else if (!PyUnicode_Check(src)) { PyErr_Format(PyExc_TypeError, "\"%s\" must be a string", name); return -1; } else { + if (PyUnicode_READY(src) == -1) + return -1; Py_XDECREF(*target); Py_INCREF(src); *target = src; @@ -357,7 +358,7 @@ return NULL; if (dialect != NULL) { - if (IS_BASESTRING(dialect)) { + if (PyUnicode_Check(dialect)) { dialect = get_dialect_from_registry(dialect); if (dialect == NULL) return NULL; @@ -808,6 +809,10 @@ Py_DECREF(lineobj); return NULL; } + if (PyUnicode_READY(lineobj) == -1) { + Py_DECREF(lineobj); + return NULL; + } ++self->line_num; kind = PyUnicode_KIND(lineobj); data = PyUnicode_DATA(lineobj); @@ -1108,6 +1113,8 @@ Py_ssize_t rec_len; if (field != NULL) { + if (PyUnicode_READY(field) == -1) + return 0; field_kind = PyUnicode_KIND(field); field_data = PyUnicode_DATA(field); field_len = PyUnicode_GET_LENGTH(field); @@ -1403,11 +1410,13 @@ if (!PyArg_UnpackTuple(args, "", 1, 2, &name_obj, &dialect_obj)) return NULL; - if (!IS_BASESTRING(name_obj)) { + if (!PyUnicode_Check(name_obj)) { PyErr_SetString(PyExc_TypeError, - "dialect name must be a string or unicode"); + "dialect name must be a string"); return NULL; } + if (PyUnicode_READY(name_obj) == -1) + return NULL; dialect = _call_dialect(dialect_obj, kwargs); if (dialect == NULL) return NULL; diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -1521,6 +1521,29 @@ } static PyObject * +unicode_legacy_string(PyObject *self, PyObject *args) +{ + Py_UNICODE *data; + Py_ssize_t len; + PyObject *u; + + if (!PyArg_ParseTuple(args, "u#", &data, &len)) + return NULL; + + u = PyUnicode_FromUnicode(NULL, len); + if (u == NULL) + return NULL; + + memcpy(PyUnicode_AS_UNICODE(u), data, len * sizeof(Py_UNICODE)); + + if (len > 0) { /* The empty string is always ready. */ + assert(!PyUnicode_IS_READY(u)); + } + + return u; +} + +static PyObject * getargs_w_star(PyObject *self, PyObject *args) { Py_buffer buffer; @@ -2506,6 +2529,7 @@ {"unicode_aswidecharstring",unicode_aswidecharstring, METH_VARARGS}, {"unicode_encodedecimal", unicode_encodedecimal, METH_VARARGS}, {"unicode_transformdecimaltoascii", unicode_transformdecimaltoascii, METH_VARARGS}, + {"unicode_legacy_string", unicode_legacy_string, METH_VARARGS}, #ifdef WITH_THREAD {"_test_thread_state", test_thread_state, METH_VARARGS}, {"_pending_threadfunc", pending_threadfunc, METH_VARARGS}, -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 18:07:03 2012 From: python-checkins at python.org (stefan.krah) Date: Fri, 2 Nov 2012 18:07:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE1ODE0?= =?utf-8?q?=3A_Use_hash_function_that_is_compatible_with_the_equality?= Message-ID: <3XtV7q58c6zRMy@mail.python.org> http://hg.python.org/cpython/rev/969069d464bc changeset: 80182:969069d464bc branch: 3.3 parent: 80180:0b5f00ccf907 user: Stefan Krah date: Fri Nov 02 17:49:22 2012 +0100 summary: Issue #15814: Use hash function that is compatible with the equality definition from #15573. files: Doc/library/stdtypes.rst | 6 ----- Lib/test/test_buffer.py | 32 ++++++++++++++++++++++++++- Objects/memoryobject.c | 8 +++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2393,12 +2393,6 @@ .. versionchanged:: 3.3 One-dimensional memoryviews with formats 'B', 'b' or 'c' are now hashable. - .. note:: - 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: .. method:: __eq__(exporter) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -3999,14 +3999,42 @@ m = memoryview(x) self.assertEqual(hash(m), hash(x)) + # equality-hash invariant + x = ndarray(list(range(12)), shape=[12], format='B') + a = memoryview(nd) + + y = ndarray(list(range(12)), shape=[12], format='b') + b = memoryview(nd) + + z = ndarray(list(bytes(chr(x), 'latin-1') for x in range(12)), + shape=[12], format='c') + c = memoryview(nd) + + if (a == b): + self.assertEqual(hash(a), hash(b)) + + if (a == c): + self.assertEqual(hash(a), hash(c)) + + if (b == c): + self.assertEqual(hash(b), hash(c)) + # non-byte formats nd = ndarray(list(range(12)), shape=[2,2,3], format='L') m = memoryview(nd) - self.assertEqual(hash(m), hash(nd.tobytes())) + self.assertRaises(ValueError, m.__hash__) nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h') m = memoryview(nd) - self.assertEqual(hash(m), hash(nd.tobytes())) + self.assertRaises(ValueError, m.__hash__) + + nd = ndarray(list(range(12)), shape=[2,2,3], format='= L') + m = memoryview(nd) + self.assertRaises(ValueError, m.__hash__) + + nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h') + m = memoryview(nd) + self.assertRaises(ValueError, m.__hash__) def test_memoryview_release(self): diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2707,6 +2707,8 @@ if (self->hash == -1) { Py_buffer *view = &self->view; char *mem = view->buf; + Py_ssize_t ret; + char fmt; CHECK_RELEASED_INT(self); @@ -2715,6 +2717,12 @@ "cannot hash writable memoryview object"); return -1; } + ret = get_native_fmtchar(&fmt, view->format); + if (ret < 0 || !IS_BYTE_FORMAT(fmt)) { + PyErr_SetString(PyExc_ValueError, + "memoryview: hashing is restricted to formats 'B', 'b' or 'c'"); + return -1; + } if (view->obj != NULL && PyObject_Hash(view->obj) == -1) { /* Keep the original error message */ return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 18:07:05 2012 From: python-checkins at python.org (stefan.krah) Date: Fri, 2 Nov 2012 18:07:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4zLg==?= Message-ID: <3XtV7s0PhwzRN6@mail.python.org> http://hg.python.org/cpython/rev/824cd6d03cb6 changeset: 80183:824cd6d03cb6 parent: 80181:f1a25c088b8f parent: 80182:969069d464bc user: Stefan Krah date: Fri Nov 02 17:55:11 2012 +0100 summary: Merge 3.3. files: Doc/library/stdtypes.rst | 6 ----- Lib/test/test_buffer.py | 32 ++++++++++++++++++++++++++- Objects/memoryobject.c | 8 +++++++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2393,12 +2393,6 @@ .. versionchanged:: 3.3 One-dimensional memoryviews with formats 'B', 'b' or 'c' are now hashable. - .. note:: - 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: .. method:: __eq__(exporter) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -3999,14 +3999,42 @@ m = memoryview(x) self.assertEqual(hash(m), hash(x)) + # equality-hash invariant + x = ndarray(list(range(12)), shape=[12], format='B') + a = memoryview(nd) + + y = ndarray(list(range(12)), shape=[12], format='b') + b = memoryview(nd) + + z = ndarray(list(bytes(chr(x), 'latin-1') for x in range(12)), + shape=[12], format='c') + c = memoryview(nd) + + if (a == b): + self.assertEqual(hash(a), hash(b)) + + if (a == c): + self.assertEqual(hash(a), hash(c)) + + if (b == c): + self.assertEqual(hash(b), hash(c)) + # non-byte formats nd = ndarray(list(range(12)), shape=[2,2,3], format='L') m = memoryview(nd) - self.assertEqual(hash(m), hash(nd.tobytes())) + self.assertRaises(ValueError, m.__hash__) nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h') m = memoryview(nd) - self.assertEqual(hash(m), hash(nd.tobytes())) + self.assertRaises(ValueError, m.__hash__) + + nd = ndarray(list(range(12)), shape=[2,2,3], format='= L') + m = memoryview(nd) + self.assertRaises(ValueError, m.__hash__) + + nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h') + m = memoryview(nd) + self.assertRaises(ValueError, m.__hash__) def test_memoryview_release(self): diff --git a/Objects/memoryobject.c b/Objects/memoryobject.c --- a/Objects/memoryobject.c +++ b/Objects/memoryobject.c @@ -2707,6 +2707,8 @@ if (self->hash == -1) { Py_buffer *view = &self->view; char *mem = view->buf; + Py_ssize_t ret; + char fmt; CHECK_RELEASED_INT(self); @@ -2715,6 +2717,12 @@ "cannot hash writable memoryview object"); return -1; } + ret = get_native_fmtchar(&fmt, view->format); + if (ret < 0 || !IS_BYTE_FORMAT(fmt)) { + PyErr_SetString(PyExc_ValueError, + "memoryview: hashing is restricted to formats 'B', 'b' or 'c'"); + return -1; + } if (view->obj != NULL && PyObject_Hash(view->obj) == -1) { /* Keep the original error message */ return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 2 19:48:59 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 2 Nov 2012 19:48:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Block_the_use_of_markup?= =?utf-8?q?safe_in_the_Mako_benchmarks_to_keep_them?= Message-ID: <3XtXPR4r9czRNs@mail.python.org> http://hg.python.org/benchmarks/rev/a4433106dbf1 changeset: 190:a4433106dbf1 user: Brett Cannon date: Fri Nov 02 14:48:53 2012 -0400 summary: Block the use of markupsafe in the Mako benchmarks to keep them consistent in case markupsafe is globally installed. files: performance/bm_mako_v2.py | 7 ++++--- 1 files changed, 4 insertions(+), 3 deletions(-) diff --git a/performance/bm_mako_v2.py b/performance/bm_mako_v2.py --- a/performance/bm_mako_v2.py +++ b/performance/bm_mako_v2.py @@ -21,7 +21,8 @@ from compat import xrange import util -# Mako imports +# Mako imports (w/o markupsafe) +sys.modules['markupsafe'] = None from mako.template import Template from mako.lookup import TemplateLookup @@ -29,7 +30,7 @@ LOREM_IPSUM = """Quisque lobortis hendrerit posuere. Curabitur aliquet consequat sapien molestie pretium. Nunc adipiscing luc tus mi, viverra porttitor lorem vulputate et. Ut at purus sem, -sed tincidunt ante. Vestibulum ante ipsum primis in faucibus +sed tincidunt ante. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Praesent pulvinar sodales justo at congue. Praesent aliquet facilisis nisl a molestie. Sed tempus nisl ut augue eleifend tincidunt. Sed a @@ -124,7 +125,7 @@ lookup.put_string('page.mako', PAGE_TEMPLATE) template = Template(CONTENT_TEMPLATE, lookup=lookup) - + table = [xrange(150) for i in xrange(150)] paragraphs = xrange(50) title = 'Hello world!' -- Repository URL: http://hg.python.org/benchmarks From python-checkins at python.org Fri Nov 2 21:07:38 2012 From: python-checkins at python.org (andrew.svetlov) Date: Fri, 2 Nov 2012 21:07:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316261=3A_fix_bare?= =?utf-8?q?_excepts_in_Doc/?= Message-ID: <3XtZ8B3xsrzRQ7@mail.python.org> http://hg.python.org/cpython/rev/b2bd62d1644f changeset: 80184:b2bd62d1644f user: Andrew Svetlov date: Fri Nov 02 22:07:26 2012 +0200 summary: Issue #16261: fix bare excepts in Doc/ files: Doc/howto/logging-cookbook.rst | 4 +--- Doc/library/timeit.rst | 2 +- Doc/library/traceback.rst | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Doc/howto/logging-cookbook.rst b/Doc/howto/logging-cookbook.rst --- a/Doc/howto/logging-cookbook.rst +++ b/Doc/howto/logging-cookbook.rst @@ -741,9 +741,7 @@ break logger = logging.getLogger(record.name) logger.handle(record) # No level or filter logic applied - just do it! - except (KeyboardInterrupt, SystemExit): - raise - except: + except Exception: import sys, traceback print('Whoops! Problem:', file=sys.stderr) traceback.print_exc(file=sys.stderr) diff --git a/Doc/library/timeit.rst b/Doc/library/timeit.rst --- a/Doc/library/timeit.rst +++ b/Doc/library/timeit.rst @@ -151,7 +151,7 @@ t = Timer(...) # outside the try/except try: t.timeit(...) # or t.repeat(...) - except: + except Exception: t.print_exc() The advantage over the standard traceback is that source lines in the diff --git a/Doc/library/traceback.rst b/Doc/library/traceback.rst --- a/Doc/library/traceback.rst +++ b/Doc/library/traceback.rst @@ -146,7 +146,7 @@ source = input(">>> ") try: exec(source, envdir) - except: + except Exception: print("Exception in user code:") print("-"*60) traceback.print_exc(file=sys.stdout) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sat Nov 3 05:54:15 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sat, 03 Nov 2012 05:54:15 +0100 Subject: [Python-checkins] Daily reference leaks (b2bd62d1644f): sum=0 Message-ID: results for b2bd62d1644f on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog7ORggT', '-x'] From ncoghlan at gmail.com Sat Nov 3 10:38:55 2012 From: ncoghlan at gmail.com (Nick Coghlan) Date: Sat, 3 Nov 2012 19:38:55 +1000 Subject: [Python-checkins] cpython (3.3): Issue #15814: Use hash function that is compatible with the equality In-Reply-To: <3XtV7q58c6zRMy@mail.python.org> References: <3XtV7q58c6zRMy@mail.python.org> Message-ID: On Sat, Nov 3, 2012 at 3:07 AM, stefan.krah wrote: > + # equality-hash invariant > + x = ndarray(list(range(12)), shape=[12], format='B') > + a = memoryview(nd) > + > + y = ndarray(list(range(12)), shape=[12], format='b') > + b = memoryview(nd) > + > + z = ndarray(list(bytes(chr(x), 'latin-1') for x in range(12)), > + shape=[12], format='c') > + c = memoryview(nd) > + > + if (a == b): > + self.assertEqual(hash(a), hash(b)) > + > + if (a == c): > + self.assertEqual(hash(a), hash(c)) > + > + if (b == c): > + self.assertEqual(hash(b), hash(c)) These checks could do with a comment explaining why the if statements are needed (I'm assuming something to do with memory order). Cheers, Nick. -- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia From python-checkins at python.org Sat Nov 3 11:50:18 2012 From: python-checkins at python.org (andrew.svetlov) Date: Sat, 3 Nov 2012 11:50:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316218=3A_Fix_brok?= =?utf-8?q?en_test_for_supporting_nonascii_characters_in_python?= Message-ID: <3Xtxkf5MqhzRLB@mail.python.org> http://hg.python.org/cpython/rev/884c2e93d3f7 changeset: 80185:884c2e93d3f7 user: Andrew Svetlov date: Sat Nov 03 12:50:01 2012 +0200 summary: Issue #16218: Fix broken test for supporting nonascii characters in python launcher files: Lib/test/test_cmd_line_script.py | 17 ++++++++++++----- 1 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -366,11 +366,18 @@ def test_non_utf8(self): # Issue #16218 with temp_dir() as script_dir: - script_name = _make_test_script(script_dir, - '\udcf1\udcea\udcf0\udce8\udcef\udcf2') - self._check_script(script_name, script_name, script_name, - script_dir, None, - importlib.machinery.SourceFileLoader) + script_basename = '\udcf1\udcea\udcf0\udce8\udcef\udcf2' + source = 'print("test output")\n' + script_name = _make_test_script(script_dir, script_basename, source) + if not __debug__: + run_args = ('-' + 'O' * sys.flags.optimize, script_name) + else: + run_args = (script_name,) + rc, out, _ = assert_python_ok(*run_args) + self.assertEqual(0, rc) + expected = ("test output" + os.linesep).encode('ascii') + self.assertEqual(expected, out) + def test_main(): support.run_unittest(CmdLineTest) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 12:53:08 2012 From: python-checkins at python.org (andrew.svetlov) Date: Sat, 3 Nov 2012 12:53:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316309=3A_Make_PYT?= =?utf-8?q?HONPATH=3D_behavior_the_same_as_if_PYTHONPATH_not_set_at?= Message-ID: <3Xtz781rcqzMDL@mail.python.org> http://hg.python.org/cpython/rev/05f8f7544f92 changeset: 80186:05f8f7544f92 user: Andrew Svetlov date: Sat Nov 03 13:52:58 2012 +0200 summary: Issue #16309: Make PYTHONPATH= behavior the same as if PYTHONPATH not set at all. Thanks to Armin Rigo and Alexey Kachayev. files: Lib/test/test_cmd_line.py | 17 +++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 +++ Modules/getpath.c | 4 +--- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -216,6 +216,23 @@ self.assertIn(path1.encode('ascii'), out) self.assertIn(path2.encode('ascii'), out) + def test_empty_PYTHONPATH_issue16309(self): + """On Posix, it is documented that setting PATH to the + empty string is equivalent to not setting PATH at all, + which is an exception to the rule that in a string like + "/bin::/usr/bin" the empty string in the middle gets + interpreted as '.'""" + code = """if 1: + import sys + path = ":".join(sys.path) + path = path.encode("ascii", "backslashreplace") + sys.stdout.buffer.write(path)""" + rc1, out1, err1 = assert_python_ok('-c', code, PYTHONPATH="") + rc2, out2, err2 = assert_python_ok('-c', code) + # regarding to Posix specification, outputs should be equal + # for empty and unset PYTHONPATH + self.assertEquals(out1, out2) + def test_displayhook_unencodable(self): for encoding in ('ascii', 'latin-1', 'utf-8'): env = os.environ.copy() diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -587,6 +587,7 @@ Andreas Jung Tattoo Mabonzo K. Bohuslav Kabrda +Alexey Kachayev Bob Kahn Kurt B. Kaiser Tamito Kajiyama diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #16309: Make PYTHONPATH="" behavior the same as if PYTHONPATH + not set at all. + - Issue #10189: Improve the error reporting of SyntaxErrors related to global and nonlocal statements. diff --git a/Modules/getpath.c b/Modules/getpath.c --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -699,13 +699,11 @@ */ bufsz = 0; - if (_rtpypath) { + if (_rtpypath && _rtpypath[0] != '\0') { size_t rtpypath_len; rtpypath = _Py_char2wchar(_rtpypath, &rtpypath_len); if (rtpypath != NULL) bufsz += rtpypath_len + 1; - else - _rtpypath = NULL; } defpath = _pythonpath; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 13:37:48 2012 From: python-checkins at python.org (andrew.svetlov) Date: Sat, 3 Nov 2012 13:37:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316218=3A_skip_tes?= =?utf-8?q?t_if_filesystem_doesn=27t_support_required_encoding?= Message-ID: <3Xv06h2mWtzMCY@mail.python.org> http://hg.python.org/cpython/rev/95d1adf144ee changeset: 80187:95d1adf144ee user: Andrew Svetlov date: Sat Nov 03 14:37:37 2012 +0200 summary: Issue #16218: skip test if filesystem doesn't support required encoding files: Lib/test/test_cmd_line_script.py | 7 ++++++- 1 files changed, 6 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -366,7 +366,12 @@ def test_non_utf8(self): # Issue #16218 with temp_dir() as script_dir: - script_basename = '\udcf1\udcea\udcf0\udce8\udcef\udcf2' + script_basename = '\u0441\u043a\u0440\u0438\u043f\u0442' + try: + script_basename.encode(sys.getfilesystemencoding()) + except UnicodeEncodeError: + raise unittest.SkipTest("Filesystem doesn't support " + "unicode names") source = 'print("test output")\n' script_name = _make_test_script(script_dir, script_basename, source) if not __debug__: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 14:36:12 2012 From: python-checkins at python.org (andrew.svetlov) Date: Sat, 3 Nov 2012 14:36:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316284=3A_Prevent_?= =?utf-8?q?keeping_unnecessary_references_to_worker_functions_in?= Message-ID: <3Xv1Q41V1wzR9J@mail.python.org> http://hg.python.org/cpython/rev/70cef0a160cf changeset: 80188:70cef0a160cf user: Andrew Svetlov date: Sat Nov 03 15:36:01 2012 +0200 summary: Issue #16284: Prevent keeping unnecessary references to worker functions in concurrent.futures ThreadPoolExecutor. files: Lib/concurrent/futures/process.py | 4 +++ Lib/concurrent/futures/thread.py | 2 + Lib/multiprocessing/queues.py | 4 +++ Lib/test/test_concurrent_futures.py | 22 +++++++++++++++++ Misc/ACKS | 1 + Misc/NEWS | 3 ++ 6 files changed, 36 insertions(+), 0 deletions(-) diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -240,6 +240,8 @@ "terminated abruptly while the future was " "running or pending." )) + # Delete references to object. See issue16284 + del work_item pending_work_items.clear() # Terminate remaining workers forcibly: the queues or their # locks may be in a dirty state and block forever. @@ -264,6 +266,8 @@ work_item.future.set_exception(result_item.exception) else: work_item.future.set_result(result_item.result) + # Delete references to object. See issue16284 + del work_item # Check whether we should start shutting down. executor = executor_reference() # No more work items can be added if: diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -63,6 +63,8 @@ work_item = work_queue.get(block=True) if work_item is not None: work_item.run() + # Delete references to object. See issue16284 + del work_item continue executor = executor_reference() # Exit if: diff --git a/Lib/multiprocessing/queues.py b/Lib/multiprocessing/queues.py --- a/Lib/multiprocessing/queues.py +++ b/Lib/multiprocessing/queues.py @@ -243,10 +243,14 @@ if wacquire is None: send(obj) + # Delete references to object. See issue16284 + del obj else: wacquire() try: send(obj) + # Delete references to object. See issue16284 + del obj finally: wrelease() except IndexError: diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -15,6 +15,7 @@ import threading import time import unittest +import weakref from concurrent import futures from concurrent.futures._base import ( @@ -52,6 +53,11 @@ sys.stdout.flush() +class MyObject(object): + def my_method(self): + pass + + class ExecutorMixin: worker_count = 5 @@ -396,6 +402,22 @@ self.executor.map(str, [2] * (self.worker_count + 1)) self.executor.shutdown() + @test.support.cpython_only + def test_no_stale_references(self): + # Issue #16284: check that the executors don't unnecessarily hang onto + # references. + my_object = MyObject() + my_object_collected = threading.Event() + my_object_callback = weakref.ref( + my_object, lambda obj: my_object_collected.set()) + # Deliberately discarding the future. + self.executor.submit(my_object.my_method) + del my_object + + collected = my_object_collected.wait(timeout=5.0) + self.assertTrue(collected, + "Stale reference not collected within timeout.") + class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest): def test_map_submits_without_iteration(self): diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -726,6 +726,7 @@ Loren Luke Fredrik Lundh Mark Lutz +Taras Lyapun Jim Lynch Mikael Lyngvig Martin von L?wis diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -88,6 +88,9 @@ Library ------- +- Issue #16284: Prevent keeping unnecessary references to worker functions + in concurrent.futures ThreadPoolExecutor. + - Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu Patch by Todd Rovito. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 14:56:23 2012 From: python-checkins at python.org (andrew.svetlov) Date: Sat, 3 Nov 2012 14:56:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=237317=3A_Display_f?= =?utf-8?q?ull_tracebacks_when_an_error_occurs_asynchronously=2E?= Message-ID: <3Xv1sM36ZczQy5@mail.python.org> http://hg.python.org/cpython/rev/a281604a5c9a changeset: 80189:a281604a5c9a user: Andrew Svetlov date: Sat Nov 03 15:56:05 2012 +0200 summary: Issue #7317: Display full tracebacks when an error occurs asynchronously. Patch by Alon Horev with update by Alexey Kachayev. files: Lib/test/test_cmd_line.py | 2 +- Lib/test/test_generators.py | 21 ++++++++++----------- Misc/NEWS | 3 +++ Python/errors.c | 15 ++++++++------- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -310,7 +310,7 @@ rc, out, err = assert_python_ok('-c', code) self.assertEqual(b'', out) self.assertRegex(err.decode('ascii', 'ignore'), - 'Exception OSError: .* ignored') + 'Exception ignored in.*\nOSError: .*') def test_closed_stdout(self): # Issue #13444: if stdout has been explicitly closed, we should diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1728,9 +1728,7 @@ >>> g = f() >>> next(g) >>> del g ->>> sys.stderr.getvalue().startswith( -... "Exception RuntimeError: 'generator ignored GeneratorExit' in " -... ) +>>> "RuntimeError: generator ignored GeneratorExit" in sys.stderr.getvalue() True >>> sys.stderr = old @@ -1840,22 +1838,23 @@ ... sys.stderr = io.StringIO() ... class Leaker: ... def __del__(self): -... raise RuntimeError +... def invoke(message): +... raise RuntimeError(message) +... invoke("test") ... ... l = Leaker() ... del l ... err = sys.stderr.getvalue().strip() -... err.startswith( -... "Exception RuntimeError: RuntimeError() in <" -... ) -... err.endswith("> ignored") -... len(err.splitlines()) +... "Exception ignored in" in err +... "RuntimeError: test" in err +... "Traceback" in err +... "in invoke" in err ... finally: ... sys.stderr = old True True -1 - +True +True These refleak tests should perhaps be in a testfile of their own, diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #7317: Display full tracebacks when an error occurs asynchronously. + Patch by Alon Horev with update by Alexey Kachayev. + - Issue #16309: Make PYTHONPATH="" behavior the same as if PYTHONPATH not set at all. diff --git a/Python/errors.c b/Python/errors.c --- a/Python/errors.c +++ b/Python/errors.c @@ -798,7 +798,12 @@ PyErr_Fetch(&t, &v, &tb); f = PySys_GetObject("stderr"); if (f != NULL && f != Py_None) { - PyFile_WriteString("Exception ", f); + if (obj) { + PyFile_WriteString("Exception ignored in: ", f); + PyFile_WriteObject(obj, f, 0); + PyFile_WriteString("\n", f); + } + PyTraceBack_Print(tb, f); if (t) { PyObject* moduleName; char* className; @@ -828,15 +833,11 @@ PyFile_WriteString(className, f); if (v && v != Py_None) { PyFile_WriteString(": ", f); - PyFile_WriteObject(v, f, 0); + PyFile_WriteObject(v, f, Py_PRINT_RAW); } + PyFile_WriteString("\n", f); Py_XDECREF(moduleName); } - if (obj) { - PyFile_WriteString(" in ", f); - PyFile_WriteObject(obj, f, 0); - } - PyFile_WriteString(" ignored\n", f); PyErr_Clear(); /* Just in case */ } Py_XDECREF(t); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 16:51:39 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 16:51:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE2MTUyOiBmaXgg?= =?utf-8?q?tokenize_to_ignore_whitespace_at_the_end_of_the_code_when_no?= Message-ID: <3Xv4QM5TnZzR8T@mail.python.org> http://hg.python.org/cpython/rev/eb7ea51e658e changeset: 80190:eb7ea51e658e branch: 2.7 parent: 80179:466cbfb3c0c6 user: Ezio Melotti date: Sat Nov 03 17:30:51 2012 +0200 summary: #16152: fix tokenize to ignore whitespace at the end of the code when no newline is found. Patch by Ned Batchelder. files: Lib/test/test_tokenize.py | 4 ++++ Lib/tokenize.py | 4 +++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -550,6 +550,10 @@ NAME 'pass' (3, 9) (3, 13) DEDENT '' (4, 0) (4, 0) DEDENT '' (4, 0) (4, 0) + +Pathological whitespace (http://bugs.python.org/issue16152) + >>> dump_tokens("@ ") + OP '@' (1, 0) (1, 1) """ diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -95,7 +95,7 @@ group("'", r'\\\r?\n'), r'[uUbB]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*' + group('"', r'\\\r?\n')) -PseudoExtras = group(r'\\\r?\n', Comment, Triple) +PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple) PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name) tokenprog, pseudoprog, single3prog, double3prog = map( @@ -362,6 +362,8 @@ if pseudomatch: # scan for tokens start, end = pseudomatch.span(1) spos, epos, pos = (lnum, start), (lnum, end), end + if start == end: + continue token, initial = line[start:end], line[start] if initial in numchars or \ diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -64,6 +64,7 @@ Ulf Bartelt Don Bashford Nick Bastin +Ned Batchelder Jeff Bauer Mike Bayer Michael R Bax diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -130,6 +130,9 @@ Library ------- +- Issue #16152: fix tokenize to ignore whitespace at the end of the code when + no newline is found. Patch by Ned Batchelder. + - Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu Patch by Todd Rovito. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 16:51:41 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 16:51:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE2MTUyOiBmaXgg?= =?utf-8?q?tokenize_to_ignore_whitespace_at_the_end_of_the_code_when_no?= Message-ID: <3Xv4QP0vsQzR8T@mail.python.org> http://hg.python.org/cpython/rev/3ffff1798ed5 changeset: 80191:3ffff1798ed5 branch: 3.2 parent: 80176:cf62fbf2171a user: Ezio Melotti date: Sat Nov 03 17:38:43 2012 +0200 summary: #16152: fix tokenize to ignore whitespace at the end of the code when no newline is found. Patch by Ned Batchelder. files: Lib/test/test_tokenize.py | 5 +++++ Lib/tokenize.py | 4 +++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 12 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -552,6 +552,11 @@ DEDENT '' (4, 0) (4, 0) DEDENT '' (4, 0) (4, 0) +Pathological whitespace (http://bugs.python.org/issue16152) + >>> dump_tokens("@ ") + ENCODING 'utf-8' (0, 0) (0, 0) + OP '@' (1, 0) (1, 1) + Non-ascii identifiers >>> dump_tokens("?rter = 'places'\\ngr?n = 'green'") diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -108,7 +108,7 @@ group("'", r'\\\r?\n'), r'[bB]?[rR]?"[^\n"\\]*(?:\\.[^\n"\\]*)*' + group('"', r'\\\r?\n')) -PseudoExtras = group(r'\\\r?\n', Comment, Triple) +PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple) PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name) def _compile(expr): @@ -473,6 +473,8 @@ if pseudomatch: # scan for tokens start, end = pseudomatch.span(1) spos, epos, pos = (lnum, start), (lnum, end), end + if start == end: + continue token, initial = line[start:end], line[start] if (initial in numchars or # ordinary number diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -71,6 +71,7 @@ Ulf Bartelt Don Bashford Nick Bastin +Ned Batchelder Jeff Bauer Mike Bayer Michael R Bax diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,6 +143,9 @@ Library ------- +- Issue #16152: fix tokenize to ignore whitespace at the end of the code when + no newline is found. Patch by Ned Batchelder. + - Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu Patch by Todd Rovito. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 16:51:42 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 16:51:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2316152=3A_merge_with_3=2E2=2E?= Message-ID: <3Xv4QQ4NprzRD3@mail.python.org> http://hg.python.org/cpython/rev/1fdeddabddda changeset: 80192:1fdeddabddda branch: 3.3 parent: 80182:969069d464bc parent: 80191:3ffff1798ed5 user: Ezio Melotti date: Sat Nov 03 17:46:51 2012 +0200 summary: #16152: merge with 3.2. files: Lib/test/test_tokenize.py | 4 ++++ Lib/tokenize.py | 4 +++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1109,6 +1109,10 @@ token.NAME, token.AMPER, token.NUMBER, token.RPAR) + def test_pathological_trailing_whitespace(self): + # See http://bugs.python.org/issue16152 + self.assertExactTypeEqual('@ ', token.AT) + __test__ = {"doctests" : doctests, 'decistmt': decistmt} def test_main(): diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -162,7 +162,7 @@ group("'", r'\\\r?\n'), StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' + group('"', r'\\\r?\n')) -PseudoExtras = group(r'\\\r?\n', Comment, Triple) +PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple) PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name) def _compile(expr): @@ -555,6 +555,8 @@ if pseudomatch: # scan for tokens start, end = pseudomatch.span(1) spos, epos, pos = (lnum, start), (lnum, end), end + if start == end: + continue token, initial = line[start:end], line[start] if (initial in numchars or # ordinary number diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -77,6 +77,7 @@ Don Bashford Pior Bastida Nick Bastin +Ned Batchelder Jeff Bauer Michael R Bax Anthony Baxter diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,9 @@ Library ------- +- Issue #16152: fix tokenize to ignore whitespace at the end of the code when + no newline is found. Patch by Ned Batchelder. + - Issue #1207589: Add Cut/Copy/Paste items to IDLE right click Context Menu Patch by Todd Rovito. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 16:51:44 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 16:51:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE2MTUyOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3Xv4QS0Mp5zRFt@mail.python.org> http://hg.python.org/cpython/rev/ed091424f230 changeset: 80193:ed091424f230 parent: 80189:a281604a5c9a parent: 80192:1fdeddabddda user: Ezio Melotti date: Sat Nov 03 17:51:25 2012 +0200 summary: #16152: merge with 3.3. files: Lib/test/test_tokenize.py | 4 ++++ Lib/tokenize.py | 4 +++- Misc/ACKS | 1 + Misc/NEWS | 3 +++ 4 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_tokenize.py b/Lib/test/test_tokenize.py --- a/Lib/test/test_tokenize.py +++ b/Lib/test/test_tokenize.py @@ -1109,6 +1109,10 @@ token.NAME, token.AMPER, token.NUMBER, token.RPAR) + def test_pathological_trailing_whitespace(self): + # See http://bugs.python.org/issue16152 + self.assertExactTypeEqual('@ ', token.AT) + __test__ = {"doctests" : doctests, 'decistmt': decistmt} def test_main(): diff --git a/Lib/tokenize.py b/Lib/tokenize.py --- a/Lib/tokenize.py +++ b/Lib/tokenize.py @@ -162,7 +162,7 @@ group("'", r'\\\r?\n'), StringPrefix + r'"[^\n"\\]*(?:\\.[^\n"\\]*)*' + group('"', r'\\\r?\n')) -PseudoExtras = group(r'\\\r?\n', Comment, Triple) +PseudoExtras = group(r'\\\r?\n|\Z', Comment, Triple) PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name) def _compile(expr): @@ -555,6 +555,8 @@ if pseudomatch: # scan for tokens start, end = pseudomatch.span(1) spos, epos, pos = (lnum, start), (lnum, end), end + if start == end: + continue token, initial = line[start:end], line[start] if (initial in numchars or # ordinary number diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -77,6 +77,7 @@ Don Bashford Pior Bastida Nick Bastin +Ned Batchelder Jeff Bauer Michael R Bax Anthony Baxter diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -91,6 +91,9 @@ Library ------- +- Issue #16152: fix tokenize to ignore whitespace at the end of the code when + no newline is found. Patch by Ned Batchelder. + - Issue #16284: Prevent keeping unnecessary references to worker functions in concurrent.futures ThreadPoolExecutor. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 17:29:44 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 17:29:44 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Remove_trailin?= =?utf-8?q?g_whitespace=2E?= Message-ID: <3Xv5GJ4ZvYzRKY@mail.python.org> http://hg.python.org/cpython/rev/d73110888af5 changeset: 80194:d73110888af5 branch: 2.7 parent: 80190:eb7ea51e658e user: Ezio Melotti date: Sat Nov 03 18:24:11 2012 +0200 summary: Remove trailing whitespace. files: Doc/tools/sphinxext/static/basic.css | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/tools/sphinxext/static/basic.css b/Doc/tools/sphinxext/static/basic.css --- a/Doc/tools/sphinxext/static/basic.css +++ b/Doc/tools/sphinxext/static/basic.css @@ -253,8 +253,8 @@ table.docutils td, table.docutils th { padding: 2px 5px 2px 5px; - border-left: 0; - background-color: #eef; + border-left: 0; + background-color: #eef; } table.docutils td p.last, table.docutils th p.last { @@ -270,7 +270,7 @@ } table.docutils th { - border-top: 1px solid #cac; + border-top: 1px solid #cac; background-color: #ede; } @@ -280,7 +280,7 @@ } th.head { - text-align: center; + text-align: center; } /* -- other body styles ----------------------------------------------------- */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 17:29:45 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 17:29:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzQ3MTE6IGJyZWFr?= =?utf-8?q?_long_words_in_the_docs_sidebar_to_avoid_overflow=2E?= Message-ID: <3Xv5GK6g2zzRJl@mail.python.org> http://hg.python.org/cpython/rev/cae65dd22826 changeset: 80195:cae65dd22826 branch: 2.7 user: Ezio Melotti date: Sat Nov 03 18:25:04 2012 +0200 summary: #4711: break long words in the docs sidebar to avoid overflow. files: Doc/tools/sphinxext/static/basic.css | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/tools/sphinxext/static/basic.css b/Doc/tools/sphinxext/static/basic.css --- a/Doc/tools/sphinxext/static/basic.css +++ b/Doc/tools/sphinxext/static/basic.css @@ -39,6 +39,7 @@ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; + word-wrap: break-word; } div.sphinxsidebar { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 17:29:47 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 17:29:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzQ3MTE6IGJyZWFr?= =?utf-8?q?_long_words_in_the_docs_sidebar_to_avoid_overflow=2E?= Message-ID: <3Xv5GM1h65zRKy@mail.python.org> http://hg.python.org/cpython/rev/1046110a819d changeset: 80196:1046110a819d branch: 3.2 parent: 80191:3ffff1798ed5 user: Ezio Melotti date: Sat Nov 03 18:25:04 2012 +0200 summary: #4711: break long words in the docs sidebar to avoid overflow. files: Doc/tools/sphinxext/static/basic.css | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/tools/sphinxext/static/basic.css b/Doc/tools/sphinxext/static/basic.css --- a/Doc/tools/sphinxext/static/basic.css +++ b/Doc/tools/sphinxext/static/basic.css @@ -39,6 +39,7 @@ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; + word-wrap: break-word; } div.sphinxsidebar { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 17:29:48 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 17:29:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=234711=3A_merge_with_3=2E2=2E?= Message-ID: <3Xv5GN3kqXzRKl@mail.python.org> http://hg.python.org/cpython/rev/1bdab9112e59 changeset: 80197:1bdab9112e59 branch: 3.3 parent: 80192:1fdeddabddda parent: 80196:1046110a819d user: Ezio Melotti date: Sat Nov 03 18:29:16 2012 +0200 summary: #4711: merge with 3.2. files: Doc/tools/sphinxext/static/basic.css | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/tools/sphinxext/static/basic.css b/Doc/tools/sphinxext/static/basic.css --- a/Doc/tools/sphinxext/static/basic.css +++ b/Doc/tools/sphinxext/static/basic.css @@ -39,6 +39,7 @@ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; + word-wrap: break-word; } div.sphinxsidebar { -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 17:29:49 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 17:29:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzQ3MTE6IG1lcmdlIHdpdGggMy4zLg==?= Message-ID: <3Xv5GP5yGzzRJl@mail.python.org> http://hg.python.org/cpython/rev/c6237edff631 changeset: 80198:c6237edff631 parent: 80193:ed091424f230 parent: 80197:1bdab9112e59 user: Ezio Melotti date: Sat Nov 03 18:29:31 2012 +0200 summary: #4711: merge with 3.3. files: Doc/tools/sphinxext/static/basic.css | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/Doc/tools/sphinxext/static/basic.css b/Doc/tools/sphinxext/static/basic.css --- a/Doc/tools/sphinxext/static/basic.css +++ b/Doc/tools/sphinxext/static/basic.css @@ -39,6 +39,7 @@ div.sphinxsidebarwrapper { padding: 10px 5px 0 10px; + word-wrap: break-word; } div.sphinxsidebar { -- Repository URL: http://hg.python.org/cpython From chris.jerdonek at gmail.com Sat Nov 3 18:36:28 2012 From: chris.jerdonek at gmail.com (Chris Jerdonek) Date: Sat, 3 Nov 2012 10:36:28 -0700 Subject: [Python-checkins] peps: Revert PEP 430 to Final. In-Reply-To: <3XqHjw6HZ6zR4V@mail.python.org> References: <3XqHjw6HZ6zR4V@mail.python.org> Message-ID: On Sun, Oct 28, 2012 at 5:07 AM, nick.coghlan wrote: > > http://hg.python.org/peps/rev/1ccf682bdfc9 > changeset: 4575:1ccf682bdfc9 > user: Nick Coghlan > date: Sun Oct 28 22:06:46 2012 +1000 > summary: > Revert PEP 430 to Final. > ... > -To help ensure future stability even of links to the in-development version, > -the ``/dev/`` subpath will be redirected to the appropriate version specific > -subpath (currently ``/3.4/``). > ... > * ``http://docs.python.org/x/*`` > * ``http://docs.python.org/x.y/*`` > +* ``http://docs.python.org/dev/*`` > * ``http://docs.python.org/release/x.y.z/*`` > * ``http://docs.python.org/devguide`` > ... > +The ``/dev/`` URL means the documentation for the default branch in source > +control. I noticed on an older issue in the tracker that the following deep, in-development link is broken: http://docs.python.org/dev/2.6/library/multiprocessing.html (in comment http://bugs.python.org/issue4711#msg78151 ) Can something be done to preserve those deep links, or is it not worth worrying about? I'm not sure how prevalent such links are or when they were valid (and when they stopped working, assuming they once did). --Chris From python-checkins at python.org Sat Nov 3 19:34:33 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 19:34:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzEyNzU5OiBzcmVf?= =?utf-8?q?parse_now_raises_a_proper_error_when_the_name_of_the_group_is?= Message-ID: <3Xv82K13b2zRGK@mail.python.org> http://hg.python.org/cpython/rev/5b5c2c3b2268 changeset: 80199:5b5c2c3b2268 branch: 2.7 parent: 80195:cae65dd22826 user: Ezio Melotti date: Sat Nov 03 20:31:12 2012 +0200 summary: #12759: sre_parse now raises a proper error when the name of the group is missing. Initial patch by Serhiy Storchaka. files: Lib/sre_parse.py | 8 +++++++- Lib/test/test_re.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 30 insertions(+), 1 deletions(-) diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -541,6 +541,8 @@ break name = name + char group = 1 + if not name: + raise error("missing group name") if not isname(name): raise error, "bad character in group name" elif sourcematch("="): @@ -553,6 +555,8 @@ if char == ")": break name = name + char + if not name: + raise error("missing group name") if not isname(name): raise error, "bad character in group name" gid = state.groupdict.get(name) @@ -605,6 +609,8 @@ break condname = condname + char group = 2 + if not condname: + raise error("missing group name") if isname(condname): condgroup = state.groupdict.get(condname) if condgroup is None: @@ -723,7 +729,7 @@ break name = name + char if not name: - raise error, "bad group name" + raise error, "missing group name" try: index = int(name) if index < 0: diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -174,11 +174,31 @@ self.assertEqual(re.sub('x*', '-', 'abxd'), '-a-b-d-') self.assertEqual(re.sub('x+', '-', 'abxd'), 'ab-d') + def test_symbolic_groups(self): + re.compile('(?Px)(?P=a)(?(a)y)') + re.compile('(?Px)(?P=a1)(?(a1)y)') + self.assertRaises(re.error, re.compile, '(?P)(?P)') + self.assertRaises(re.error, re.compile, '(?Px)') + self.assertRaises(re.error, re.compile, '(?P=)') + self.assertRaises(re.error, re.compile, '(?P=1)') + self.assertRaises(re.error, re.compile, '(?P=a)') + self.assertRaises(re.error, re.compile, '(?P=a1)') + self.assertRaises(re.error, re.compile, '(?P=a.)') + self.assertRaises(re.error, re.compile, '(?P<)') + self.assertRaises(re.error, re.compile, '(?P<>)') + self.assertRaises(re.error, re.compile, '(?P<1>)') + self.assertRaises(re.error, re.compile, '(?P)') + self.assertRaises(re.error, re.compile, '(?())') + self.assertRaises(re.error, re.compile, '(?(a))') + self.assertRaises(re.error, re.compile, '(?(1a))') + self.assertRaises(re.error, re.compile, '(?(a.))') + def test_symbolic_refs(self): self.assertRaises(re.error, re.sub, '(?Px)', '\gx)', '\g<', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g', 'xx') + self.assertRaises(re.error, re.sub, '(?Px)', '\g<>', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g<1a1>', 'xx') self.assertRaises(IndexError, re.sub, '(?Px)', '\g', 'xx') self.assertRaises(re.error, re.sub, '(?Px)|(?Py)', '\g', 'xx') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -130,6 +130,9 @@ Library ------- +- Issue #12759: sre_parse now raises a proper error when the name of the group + is missing. Initial patch by Serhiy Storchaka. + - Issue #16152: fix tokenize to ignore whitespace at the end of the code when no newline is found. Patch by Ned Batchelder. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 19:34:34 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 19:34:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzEyNzU5OiBzcmVf?= =?utf-8?q?parse_now_raises_a_proper_error_when_the_name_of_the_group_is?= Message-ID: <3Xv82L4Sg3zRJb@mail.python.org> http://hg.python.org/cpython/rev/29983dd7191e changeset: 80200:29983dd7191e branch: 3.2 parent: 80196:1046110a819d user: Ezio Melotti date: Sat Nov 03 20:33:08 2012 +0200 summary: #12759: sre_parse now raises a proper error when the name of the group is missing. Initial patch by Serhiy Storchaka. files: Lib/sre_parse.py | 8 +++++++- Lib/test/test_re.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 30 insertions(+), 1 deletions(-) diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -548,6 +548,8 @@ break name = name + char group = 1 + if not name: + raise error("missing group name") if not isname(name): raise error("bad character in group name") elif sourcematch("="): @@ -560,6 +562,8 @@ if char == ")": break name = name + char + if not name: + raise error("missing group name") if not isname(name): raise error("bad character in group name") gid = state.groupdict.get(name) @@ -612,6 +616,8 @@ break condname = condname + char group = 2 + if not condname: + raise error("missing group name") if isname(condname): condgroup = state.groupdict.get(condname) if condgroup is None: @@ -743,7 +749,7 @@ break name = name + char if not name: - raise error("bad group name") + raise error("missing group name") try: index = int(name) if index < 0: diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -161,11 +161,31 @@ self.assertEqual(re.sub('x*', '-', 'abxd'), '-a-b-d-') self.assertEqual(re.sub('x+', '-', 'abxd'), 'ab-d') + def test_symbolic_groups(self): + re.compile('(?Px)(?P=a)(?(a)y)') + re.compile('(?Px)(?P=a1)(?(a1)y)') + self.assertRaises(re.error, re.compile, '(?P)(?P)') + self.assertRaises(re.error, re.compile, '(?Px)') + self.assertRaises(re.error, re.compile, '(?P=)') + self.assertRaises(re.error, re.compile, '(?P=1)') + self.assertRaises(re.error, re.compile, '(?P=a)') + self.assertRaises(re.error, re.compile, '(?P=a1)') + self.assertRaises(re.error, re.compile, '(?P=a.)') + self.assertRaises(re.error, re.compile, '(?P<)') + self.assertRaises(re.error, re.compile, '(?P<>)') + self.assertRaises(re.error, re.compile, '(?P<1>)') + self.assertRaises(re.error, re.compile, '(?P)') + self.assertRaises(re.error, re.compile, '(?())') + self.assertRaises(re.error, re.compile, '(?(a))') + self.assertRaises(re.error, re.compile, '(?(1a))') + self.assertRaises(re.error, re.compile, '(?(a.))') + def test_symbolic_refs(self): self.assertRaises(re.error, re.sub, '(?Px)', '\gx)', '\g<', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g', 'xx') + self.assertRaises(re.error, re.sub, '(?Px)', '\g<>', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g<1a1>', 'xx') self.assertRaises(IndexError, re.sub, '(?Px)', '\g', 'xx') self.assertRaises(re.error, re.sub, '(?Px)|(?Py)', '\g', 'xx') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -143,6 +143,9 @@ Library ------- +- Issue #12759: sre_parse now raises a proper error when the name of the group + is missing. Initial patch by Serhiy Storchaka. + - Issue #16152: fix tokenize to ignore whitespace at the end of the code when no newline is found. Patch by Ned Batchelder. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 19:34:36 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 19:34:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2312759=3A_merge_with_3=2E2=2E?= Message-ID: <3Xv82N12V9zRJs@mail.python.org> http://hg.python.org/cpython/rev/28be586287c8 changeset: 80201:28be586287c8 branch: 3.3 parent: 80197:1bdab9112e59 parent: 80200:29983dd7191e user: Ezio Melotti date: Sat Nov 03 20:33:38 2012 +0200 summary: #12759: merge with 3.2. files: Lib/sre_parse.py | 8 +++++++- Lib/test/test_re.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 30 insertions(+), 1 deletions(-) diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -580,6 +580,8 @@ break name = name + char group = 1 + if not name: + raise error("missing group name") if not isname(name): raise error("bad character in group name") elif sourcematch("="): @@ -592,6 +594,8 @@ if char == ")": break name = name + char + if not name: + raise error("missing group name") if not isname(name): raise error("bad character in group name") gid = state.groupdict.get(name) @@ -644,6 +648,8 @@ break condname = condname + char group = 2 + if not condname: + raise error("missing group name") if isname(condname): condgroup = state.groupdict.get(condname) if condgroup is None: @@ -775,7 +781,7 @@ break name = name + char if not name: - raise error("bad group name") + raise error("missing group name") try: index = int(name) if index < 0: diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -161,11 +161,31 @@ self.assertEqual(re.sub('x*', '-', 'abxd'), '-a-b-d-') self.assertEqual(re.sub('x+', '-', 'abxd'), 'ab-d') + def test_symbolic_groups(self): + re.compile('(?Px)(?P=a)(?(a)y)') + re.compile('(?Px)(?P=a1)(?(a1)y)') + self.assertRaises(re.error, re.compile, '(?P)(?P)') + self.assertRaises(re.error, re.compile, '(?Px)') + self.assertRaises(re.error, re.compile, '(?P=)') + self.assertRaises(re.error, re.compile, '(?P=1)') + self.assertRaises(re.error, re.compile, '(?P=a)') + self.assertRaises(re.error, re.compile, '(?P=a1)') + self.assertRaises(re.error, re.compile, '(?P=a.)') + self.assertRaises(re.error, re.compile, '(?P<)') + self.assertRaises(re.error, re.compile, '(?P<>)') + self.assertRaises(re.error, re.compile, '(?P<1>)') + self.assertRaises(re.error, re.compile, '(?P)') + self.assertRaises(re.error, re.compile, '(?())') + self.assertRaises(re.error, re.compile, '(?(a))') + self.assertRaises(re.error, re.compile, '(?(1a))') + self.assertRaises(re.error, re.compile, '(?(a.))') + def test_symbolic_refs(self): self.assertRaises(re.error, re.sub, '(?Px)', '\gx)', '\g<', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g', 'xx') + self.assertRaises(re.error, re.sub, '(?Px)', '\g<>', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g<1a1>', 'xx') self.assertRaises(IndexError, re.sub, '(?Px)', '\g', 'xx') self.assertRaises(re.error, re.sub, '(?Px)|(?Py)', '\g', 'xx') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -61,6 +61,9 @@ Library ------- +- Issue #12759: sre_parse now raises a proper error when the name of the group + is missing. Initial patch by Serhiy Storchaka. + - Issue #16152: fix tokenize to ignore whitespace at the end of the code when no newline is found. Patch by Ned Batchelder. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 19:34:37 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 19:34:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzEyNzU5OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3Xv82P4MRKzRJq@mail.python.org> http://hg.python.org/cpython/rev/3f4fbad75c99 changeset: 80202:3f4fbad75c99 parent: 80198:c6237edff631 parent: 80201:28be586287c8 user: Ezio Melotti date: Sat Nov 03 20:34:16 2012 +0200 summary: #12759: merge with 3.3. files: Lib/sre_parse.py | 8 +++++++- Lib/test/test_re.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ 3 files changed, 30 insertions(+), 1 deletions(-) diff --git a/Lib/sre_parse.py b/Lib/sre_parse.py --- a/Lib/sre_parse.py +++ b/Lib/sre_parse.py @@ -580,6 +580,8 @@ break name = name + char group = 1 + if not name: + raise error("missing group name") if not isname(name): raise error("bad character in group name") elif sourcematch("="): @@ -592,6 +594,8 @@ if char == ")": break name = name + char + if not name: + raise error("missing group name") if not isname(name): raise error("bad character in group name") gid = state.groupdict.get(name) @@ -644,6 +648,8 @@ break condname = condname + char group = 2 + if not condname: + raise error("missing group name") if isname(condname): condgroup = state.groupdict.get(condname) if condgroup is None: @@ -775,7 +781,7 @@ break name = name + char if not name: - raise error("bad group name") + raise error("missing group name") try: index = int(name) if index < 0: diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -161,11 +161,31 @@ self.assertEqual(re.sub('x*', '-', 'abxd'), '-a-b-d-') self.assertEqual(re.sub('x+', '-', 'abxd'), 'ab-d') + def test_symbolic_groups(self): + re.compile('(?Px)(?P=a)(?(a)y)') + re.compile('(?Px)(?P=a1)(?(a1)y)') + self.assertRaises(re.error, re.compile, '(?P)(?P)') + self.assertRaises(re.error, re.compile, '(?Px)') + self.assertRaises(re.error, re.compile, '(?P=)') + self.assertRaises(re.error, re.compile, '(?P=1)') + self.assertRaises(re.error, re.compile, '(?P=a)') + self.assertRaises(re.error, re.compile, '(?P=a1)') + self.assertRaises(re.error, re.compile, '(?P=a.)') + self.assertRaises(re.error, re.compile, '(?P<)') + self.assertRaises(re.error, re.compile, '(?P<>)') + self.assertRaises(re.error, re.compile, '(?P<1>)') + self.assertRaises(re.error, re.compile, '(?P)') + self.assertRaises(re.error, re.compile, '(?())') + self.assertRaises(re.error, re.compile, '(?(a))') + self.assertRaises(re.error, re.compile, '(?(1a))') + self.assertRaises(re.error, re.compile, '(?(a.))') + def test_symbolic_refs(self): self.assertRaises(re.error, re.sub, '(?Px)', '\gx)', '\g<', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g', 'xx') + self.assertRaises(re.error, re.sub, '(?Px)', '\g<>', 'xx') self.assertRaises(re.error, re.sub, '(?Px)', '\g<1a1>', 'xx') self.assertRaises(IndexError, re.sub, '(?Px)', '\g', 'xx') self.assertRaises(re.error, re.sub, '(?Px)|(?Py)', '\g', 'xx') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -91,6 +91,9 @@ Library ------- +- Issue #12759: sre_parse now raises a proper error when the name of the group + is missing. Initial patch by Serhiy Storchaka. + - Issue #16152: fix tokenize to ignore whitespace at the end of the code when no newline is found. Patch by Ned Batchelder. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:14:47 2012 From: python-checkins at python.org (chris.jerdonek) Date: Sat, 3 Nov 2012 20:14:47 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Link_to_mappin?= =?utf-8?q?g_glossary_entry_in_=22Mapping_Types_-_dict=22_and_os=2Eenviron?= =?utf-8?q?_docs=2E?= Message-ID: <3Xv8wl3GztzRHd@mail.python.org> http://hg.python.org/cpython/rev/18076647922a changeset: 80203:18076647922a branch: 3.2 parent: 80200:29983dd7191e user: Chris Jerdonek date: Sat Nov 03 12:05:55 2012 -0700 summary: Link to mapping glossary entry in "Mapping Types - dict" and os.environ docs. files: Doc/library/os.rst | 4 ++-- Doc/library/stdtypes.rst | 2 +- 2 files changed, 3 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 @@ -98,7 +98,7 @@ .. data:: environ - A mapping object representing the string environment. For example, + A :term:`mapping` object representing the string environment. For example, ``environ['HOME']`` is the pathname of your home directory (on some platforms), and is equivalent to ``getenv("HOME")`` in C. @@ -138,7 +138,7 @@ .. data:: environb - Bytes version of :data:`environ`: a mapping object representing the + Bytes version of :data:`environ`: a :term:`mapping` object representing the environment as byte strings. :data:`environ` and :data:`environb` are synchronized (modify :data:`environb` updates :data:`environ`, and vice versa). diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2095,7 +2095,7 @@ statement: del builtin: len -A :dfn:`mapping` object maps :term:`hashable` values to arbitrary objects. +A :term:`mapping` object maps :term:`hashable` values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the :dfn:`dictionary`. (For other containers see the built in :class:`list`, :class:`set`, and :class:`tuple` classes, and the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:14:48 2012 From: python-checkins at python.org (chris.jerdonek) Date: Sat, 3 Nov 2012 20:14:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_from_3=2E2=3A_link_to_mapping_glossary_entry_in_docs=2E?= Message-ID: <3Xv8wm5fYYzRHd@mail.python.org> http://hg.python.org/cpython/rev/5982a6ea124f changeset: 80204:5982a6ea124f branch: 3.3 parent: 80201:28be586287c8 parent: 80203:18076647922a user: Chris Jerdonek date: Sat Nov 03 12:06:42 2012 -0700 summary: Merge from 3.2: link to mapping glossary entry in docs. files: Doc/library/os.rst | 4 ++-- Doc/library/stdtypes.rst | 2 +- 2 files changed, 3 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 @@ -105,7 +105,7 @@ .. data:: environ - A mapping object representing the string environment. For example, + A :term:`mapping` object representing the string environment. For example, ``environ['HOME']`` is the pathname of your home directory (on some platforms), and is equivalent to ``getenv("HOME")`` in C. @@ -145,7 +145,7 @@ .. data:: environb - Bytes version of :data:`environ`: a mapping object representing the + Bytes version of :data:`environ`: a :term:`mapping` object representing the environment as byte strings. :data:`environ` and :data:`environb` are synchronized (modify :data:`environb` updates :data:`environ`, and vice versa). diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2928,7 +2928,7 @@ statement: del builtin: len -A :dfn:`mapping` object maps :term:`hashable` values to arbitrary objects. +A :term:`mapping` object maps :term:`hashable` values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the :dfn:`dictionary`. (For other containers see the built-in :class:`list`, :class:`set`, and :class:`tuple` classes, and the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:14:50 2012 From: python-checkins at python.org (chris.jerdonek) Date: Sat, 3 Nov 2012 20:14:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E3=3A_link_to_mapping_glossary_entry_in_do?= =?utf-8?b?Y3Mu?= Message-ID: <3Xv8wp114zzRJ7@mail.python.org> http://hg.python.org/cpython/rev/3d467c6e7469 changeset: 80205:3d467c6e7469 parent: 80202:3f4fbad75c99 parent: 80204:5982a6ea124f user: Chris Jerdonek date: Sat Nov 03 12:07:20 2012 -0700 summary: Merge from 3.3: link to mapping glossary entry in docs. files: Doc/library/os.rst | 4 ++-- Doc/library/stdtypes.rst | 2 +- 2 files changed, 3 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 @@ -105,7 +105,7 @@ .. data:: environ - A mapping object representing the string environment. For example, + A :term:`mapping` object representing the string environment. For example, ``environ['HOME']`` is the pathname of your home directory (on some platforms), and is equivalent to ``getenv("HOME")`` in C. @@ -145,7 +145,7 @@ .. data:: environb - Bytes version of :data:`environ`: a mapping object representing the + Bytes version of :data:`environ`: a :term:`mapping` object representing the environment as byte strings. :data:`environ` and :data:`environb` are synchronized (modify :data:`environb` updates :data:`environ`, and vice versa). diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2928,7 +2928,7 @@ statement: del builtin: len -A :dfn:`mapping` object maps :term:`hashable` values to arbitrary objects. +A :term:`mapping` object maps :term:`hashable` values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the :dfn:`dictionary`. (For other containers see the built-in :class:`list`, :class:`set`, and :class:`tuple` classes, and the -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:14:51 2012 From: python-checkins at python.org (chris.jerdonek) Date: Sat, 3 Nov 2012 20:14:51 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Backport_from_?= =?utf-8?q?3=2E2=3A_link_to_mapping_glossary_entry_in_docs=2E?= Message-ID: <3Xv8wq38kWzRJl@mail.python.org> http://hg.python.org/cpython/rev/781817bbee28 changeset: 80206:781817bbee28 branch: 2.7 parent: 80199:5b5c2c3b2268 user: Chris Jerdonek date: Sat Nov 03 12:13:46 2012 -0700 summary: Backport from 3.2: link to mapping glossary entry in docs. files: Doc/library/os.rst | 2 +- Doc/library/stdtypes.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/library/os.rst b/Doc/library/os.rst --- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -72,7 +72,7 @@ .. data:: environ - A mapping object representing the string environment. For example, + A :term:`mapping` object representing the string environment. For example, ``environ['HOME']`` is the pathname of your home directory (on some platforms), and is equivalent to ``getenv("HOME")`` in C. diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1937,7 +1937,7 @@ statement: del builtin: len -A :dfn:`mapping` object maps :term:`hashable` values to arbitrary objects. +A :term:`mapping` object maps :term:`hashable` values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the :dfn:`dictionary`. (For other containers see the built in :class:`list`, :class:`set`, and :class:`tuple` classes, and the -- Repository URL: http://hg.python.org/cpython From tjreedy at udel.edu Sat Nov 3 19:18:17 2012 From: tjreedy at udel.edu (Terry Reedy) Date: Sat, 03 Nov 2012 14:18:17 -0400 Subject: [Python-checkins] peps: Revert PEP 430 to Final. In-Reply-To: References: <3XqHjw6HZ6zR4V@mail.python.org> Message-ID: <50955FE9.3000400@udel.edu> On 11/3/2012 1:36 PM, Chris Jerdonek wrote: > On Sun, Oct 28, 2012 at 5:07 AM, nick.coghlan > wrote: >> >> http://hg.python.org/peps/rev/1ccf682bdfc9 >> changeset: 4575:1ccf682bdfc9 >> user: Nick Coghlan >> date: Sun Oct 28 22:06:46 2012 +1000 >> summary: >> Revert PEP 430 to Final. >> ... >> -To help ensure future stability even of links to the in-development version, >> -the ``/dev/`` subpath will be redirected to the appropriate version specific >> -subpath (currently ``/3.4/``). >> ... >> * ``http://docs.python.org/x/*`` >> * ``http://docs.python.org/x.y/*`` >> +* ``http://docs.python.org/dev/*`` >> * ``http://docs.python.org/release/x.y.z/*`` >> * ``http://docs.python.org/devguide`` >> ... >> +The ``/dev/`` URL means the documentation for the default branch in source >> +control. > > I noticed on an older issue in the tracker that the following deep, > in-development link is broken: > > http://docs.python.org/dev/2.6/library/multiprocessing.html > > (in comment http://bugs.python.org/issue4711#msg78151 ) > > Can something be done to preserve those deep links, or is it not worth > worrying about? I'm not sure how prevalent such links are or when > they were valid (and when they stopped working, assuming they once > did). I'd say not bother. The message was posted 2008-12-11 and the link was already obsolete when Ezio answered 2009-07-01, when he gave a permanent one. Fortunately, the OP gave a .png screenshot showing the problem. Any doc link in the tracker becomes obsolete in a sense as soon as the problem noted is fixed. So tracker messages should state the problem independently of the link. (After the docs are rebuilt tonight, http://docs.python.org/library/multiprocessing.html will no longer exhibit the problem either ;-). -- Terry From python-checkins at python.org Sat Nov 3 20:25:04 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:25:04 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzg0MDE6IGFzc2ln?= =?utf-8?q?ning_an_int_to_a_bytearray_slice_=28e=2Eg=2E_b=5B3=3A4=5D_=3D_5?= =?utf-8?q?=29_now_raises_an?= Message-ID: <3Xv98c0m3hzPbB@mail.python.org> http://hg.python.org/cpython/rev/1bd2b272c568 changeset: 80207:1bd2b272c568 branch: 2.7 parent: 80199:5b5c2c3b2268 user: Ezio Melotti date: Sat Nov 03 21:10:45 2012 +0200 summary: #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now raises an error. files: Lib/test/test_bytes.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 6 ++++++ 3 files changed, 29 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -635,6 +635,26 @@ b[3:0] = [42, 42, 42] self.assertEqual(b, bytearray([0, 1, 2, 42, 42, 42, 3, 4, 5, 6, 7, 8, 9])) + b[3:] = b'foo' + self.assertEqual(b, bytearray([0, 1, 2, 102, 111, 111])) + + b[:3] = memoryview(b'foo') + self.assertEqual(b, bytearray([102, 111, 111, 102, 111, 111])) + + b[3:4] = [] + self.assertEqual(b, bytearray([102, 111, 111, 111, 111])) + + b[1:] = list(b'uuuu') # this works only on Python2 + self.assertEqual(b, bytearray([102, 117, 117, 117, 117])) + + for elem in [5, -5, 0, long(10e20), u'str', 2.3, [u'a', u'b'], [[]]]: + with self.assertRaises(TypeError): + b[3:4] = elem + + for elem in [[254, 255, 256], [-256, 9000]]: + with self.assertRaises(ValueError): + b[3:4] = elem + def test_extended_set_del_slice(self): indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300) for start in indices: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ Core and Builtins ----------------- +- Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now + raises an error. + - Issue #14700: Fix buggy overflow checks for large width and precision in string formatting operations. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -636,6 +636,12 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + if (PyNumber_Check(values) || PyUnicode_Check(values)) { + PyErr_SetString(PyExc_TypeError, + "can assign only bytes, buffers, or iterables " + "of ints in range(0, 256)"); + return -1; + } /* Make a copy and call this function recursively */ int err; values = PyByteArray_FromObject(values); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:25:05 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:25:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMi43IC0+IDIuNyk6?= =?utf-8?q?_Merge_heads=2E?= Message-ID: <3Xv98d38nqzRGJ@mail.python.org> http://hg.python.org/cpython/rev/35d85c5c6722 changeset: 80208:35d85c5c6722 branch: 2.7 parent: 80206:781817bbee28 parent: 80207:1bd2b272c568 user: Ezio Melotti date: Sat Nov 03 21:18:57 2012 +0200 summary: Merge heads. files: Lib/test/test_bytes.py | 20 ++++++++++++++++++++ Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 6 ++++++ 3 files changed, 29 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -635,6 +635,26 @@ b[3:0] = [42, 42, 42] self.assertEqual(b, bytearray([0, 1, 2, 42, 42, 42, 3, 4, 5, 6, 7, 8, 9])) + b[3:] = b'foo' + self.assertEqual(b, bytearray([0, 1, 2, 102, 111, 111])) + + b[:3] = memoryview(b'foo') + self.assertEqual(b, bytearray([102, 111, 111, 102, 111, 111])) + + b[3:4] = [] + self.assertEqual(b, bytearray([102, 111, 111, 111, 111])) + + b[1:] = list(b'uuuu') # this works only on Python2 + self.assertEqual(b, bytearray([102, 117, 117, 117, 117])) + + for elem in [5, -5, 0, long(10e20), u'str', 2.3, [u'a', u'b'], [[]]]: + with self.assertRaises(TypeError): + b[3:4] = elem + + for elem in [[254, 255, 256], [-256, 9000]]: + with self.assertRaises(ValueError): + b[3:4] = elem + def test_extended_set_del_slice(self): indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300) for start in indices: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ Core and Builtins ----------------- +- Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now + raises an error. + - Issue #14700: Fix buggy overflow checks for large width and precision in string formatting operations. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -636,6 +636,12 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + if (PyNumber_Check(values) || PyUnicode_Check(values)) { + PyErr_SetString(PyExc_TypeError, + "can assign only bytes, buffers, or iterables " + "of ints in range(0, 256)"); + return -1; + } /* Make a copy and call this function recursively */ int err; values = PyByteArray_FromObject(values); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:25:06 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:25:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzg0MDE6IGFzc2ln?= =?utf-8?q?ning_an_int_to_a_bytearray_slice_=28e=2Eg=2E_b=5B3=3A4=5D_=3D_5?= =?utf-8?q?=29_now_raises_an?= Message-ID: <3Xv98f5xkhzRJ5@mail.python.org> http://hg.python.org/cpython/rev/8f00af8abaf9 changeset: 80209:8f00af8abaf9 branch: 3.2 parent: 80203:18076647922a user: Ezio Melotti date: Sat Nov 03 21:19:06 2012 +0200 summary: #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now raises an error. files: Lib/test/test_bytes.py | 18 ++++++++++++++++++ Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 6 ++++++ 3 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -705,6 +705,24 @@ b[3:0] = [42, 42, 42] self.assertEqual(b, bytearray([0, 1, 2, 42, 42, 42, 3, 4, 5, 6, 7, 8, 9])) + b[3:] = b'foo' + self.assertEqual(b, bytearray([0, 1, 2, 102, 111, 111])) + + b[:3] = memoryview(b'foo') + self.assertEqual(b, bytearray([102, 111, 111, 102, 111, 111])) + + b[3:4] = [] + self.assertEqual(b, bytearray([102, 111, 111, 111, 111])) + + for elem in [5, -5, 0, int(10e20), 'str', 2.3, + ['a', 'b'], [b'a', b'b'], [[]]]: + with self.assertRaises(TypeError): + b[3:4] = elem + + for elem in [[254, 255, 256], [-256, 9000]]: + with self.assertRaises(ValueError): + b[3:4] = elem + def test_extended_set_del_slice(self): indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300) for start in indices: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now + raises an error. + - Issue #16345: Fix an infinite loop when ``fromkeys`` on a dict subclass received a nonempty dict from the constructor. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -589,6 +589,12 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + if (PyNumber_Check(values) || PyUnicode_Check(values)) { + PyErr_SetString(PyExc_TypeError, + "can assign only bytes, buffers, or iterables " + "of ints in range(0, 256)"); + return -1; + } /* Make a copy and call this function recursively */ int err; values = PyByteArray_FromObject(values); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:25:08 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:25:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=238401=3A_merge_with_3=2E2=2E?= Message-ID: <3Xv98h1Fc1zRJN@mail.python.org> http://hg.python.org/cpython/rev/06577f6b1c99 changeset: 80210:06577f6b1c99 branch: 3.3 parent: 80204:5982a6ea124f parent: 80209:8f00af8abaf9 user: Ezio Melotti date: Sat Nov 03 21:22:41 2012 +0200 summary: #8401: merge with 3.2. files: Lib/test/test_bytes.py | 18 ++++++++++++++++++ Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 6 ++++++ 3 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -871,6 +871,24 @@ b[3:0] = [42, 42, 42] self.assertEqual(b, bytearray([0, 1, 2, 42, 42, 42, 3, 4, 5, 6, 7, 8, 9])) + b[3:] = b'foo' + self.assertEqual(b, bytearray([0, 1, 2, 102, 111, 111])) + + b[:3] = memoryview(b'foo') + self.assertEqual(b, bytearray([102, 111, 111, 102, 111, 111])) + + b[3:4] = [] + self.assertEqual(b, bytearray([102, 111, 111, 111, 111])) + + for elem in [5, -5, 0, int(10e20), 'str', 2.3, + ['a', 'b'], [b'a', b'b'], [[]]]: + with self.assertRaises(TypeError): + b[3:4] = elem + + for elem in [[254, 255, 256], [-256, 9000]]: + with self.assertRaises(ValueError): + b[3:4] = elem + def test_extended_set_del_slice(self): indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300) for start in indices: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now + raises an error. + - Fix segfaults on setting __qualname__ on builtin types and attempting to delete it on any type. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -589,6 +589,12 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + if (PyNumber_Check(values) || PyUnicode_Check(values)) { + PyErr_SetString(PyExc_TypeError, + "can assign only bytes, buffers, or iterables " + "of ints in range(0, 256)"); + return -1; + } /* Make a copy and call this function recursively */ int err; values = PyByteArray_FromObject(values); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:25:09 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:25:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E2_-=3E_default?= =?utf-8?b?KTogIzg0MDE6IG1lcmdlIHdpdGggMy4zLg==?= Message-ID: <3Xv98j3XRWzRGJ@mail.python.org> http://hg.python.org/cpython/rev/db40752c6cc7 changeset: 80211:db40752c6cc7 parent: 80205:3d467c6e7469 parent: 80209:8f00af8abaf9 user: Ezio Melotti date: Sat Nov 03 21:24:47 2012 +0200 summary: #8401: merge with 3.3. files: Lib/test/test_bytes.py | 18 ++++++++++++++++++ Misc/NEWS | 3 +++ Objects/bytearrayobject.c | 6 ++++++ 3 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_bytes.py b/Lib/test/test_bytes.py --- a/Lib/test/test_bytes.py +++ b/Lib/test/test_bytes.py @@ -885,6 +885,24 @@ b[3:0] = [42, 42, 42] self.assertEqual(b, bytearray([0, 1, 2, 42, 42, 42, 3, 4, 5, 6, 7, 8, 9])) + b[3:] = b'foo' + self.assertEqual(b, bytearray([0, 1, 2, 102, 111, 111])) + + b[:3] = memoryview(b'foo') + self.assertEqual(b, bytearray([102, 111, 111, 102, 111, 111])) + + b[3:4] = [] + self.assertEqual(b, bytearray([102, 111, 111, 111, 111])) + + for elem in [5, -5, 0, int(10e20), 'str', 2.3, + ['a', 'b'], [b'a', b'b'], [[]]]: + with self.assertRaises(TypeError): + b[3:4] = elem + + for elem in [[254, 255, 256], [-256, 9000]]: + with self.assertRaises(ValueError): + b[3:4] = elem + def test_extended_set_del_slice(self): indices = (0, None, 1, 3, 19, 300, 1<<333, -1, -2, -31, -300) for start in indices: diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now + raises an error. + - Issue #7317: Display full tracebacks when an error occurs asynchronously. Patch by Alon Horev with update by Alexey Kachayev. diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -589,6 +589,12 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + if (PyNumber_Check(values) || PyUnicode_Check(values)) { + PyErr_SetString(PyExc_TypeError, + "can assign only bytes, buffers, or iterables " + "of ints in range(0, 256)"); + return -1; + } /* Make a copy and call this function recursively */ int err; values = PyByteArray_FromObject(values); -- Repository URL: http://hg.python.org/cpython From chris.jerdonek at gmail.com Sat Nov 3 20:36:36 2012 From: chris.jerdonek at gmail.com (Chris Jerdonek) Date: Sat, 3 Nov 2012 12:36:36 -0700 Subject: [Python-checkins] peps: Revert PEP 430 to Final. In-Reply-To: <50955FE9.3000400@udel.edu> References: <3XqHjw6HZ6zR4V@mail.python.org> <50955FE9.3000400@udel.edu> Message-ID: On Sat, Nov 3, 2012 at 11:18 AM, Terry Reedy wrote: > > On 11/3/2012 1:36 PM, Chris Jerdonek wrote: >> >> I noticed on an older issue in the tracker that the following deep, >> in-development link is broken: >> >> http://docs.python.org/dev/2.6/library/multiprocessing.html >> >> (in comment http://bugs.python.org/issue4711#msg78151 ) >> >> Can something be done to preserve those deep links, or is it not worth >> worrying about? I'm not sure how prevalent such links are or when >> they were valid (and when they stopped working, assuming they once >> did). > > > I'd say not bother. The message was posted 2008-12-11 and the link was > already obsolete when Ezio answered 2009-07-01, when he gave a permanent > one. Fortunately, the OP gave a .png screenshot showing the problem. > > Any doc link in the tracker becomes obsolete in a sense as soon as the > problem noted is fixed. So tracker messages should state the problem > independently of the link. (After the docs are rebuilt tonight, > http://docs.python.org/library/multiprocessing.html > will no longer exhibit the problem either ;-). Though this link will still exhibit it (which may be what it would redirect to): http://docs.python.org/2.6/library/multiprocessing.html So a doc link in the tracker won't become obsolete if we wait long enough to fix the issue. :) --Chris From python-checkins at python.org Sat Nov 3 20:36:46 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:36:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fix_a_couple_t?= =?utf-8?q?ypos_in_Misc/NEWS=2E?= Message-ID: <3Xv9Q65gjfzRH9@mail.python.org> http://hg.python.org/cpython/rev/23b21deef18f changeset: 80212:23b21deef18f branch: 2.7 parent: 80208:35d85c5c6722 user: Ezio Melotti date: Sat Nov 03 21:29:08 2012 +0200 summary: Fix a couple typos in Misc/NEWS. files: Misc/NEWS | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -58,7 +58,7 @@ - Issue #16369: Global PyTypeObjects not initialized with PyType_Ready(...). -- Issue #15033: Fix the exit status bug when modules invoked using -m swith, +- Issue #15033: Fix the exit status bug when modules invoked using -m switch, return the proper failure return value (1). Patch contributed by Jeff Knupp. - Issue #12268: File readline, readlines and read() methods no longer lose @@ -1349,7 +1349,7 @@ - Issue #11927: SMTP_SSL now uses port 465 by default as documented. Patch by Kasun Herath. -- Issue 11999: fixed sporadic sync failure mailbox.Maildir due to its trying to +- Issue #11999: fixed sporadic sync failure mailbox.Maildir due to its trying to detect mtime changes by comparing to the system clock instead of to the previous value of the mtime. @@ -4923,7 +4923,7 @@ - Restore Python 2.3 compatibility for decimal.py. - Issue #1702551: distutils sdist was not excluding VCS directories under - Windows. Inital solution by Guy Dalberto. + Windows. Initial solution by Guy Dalberto. - The _tkinter module functions "createfilehandler", "deletefilehandler", "createtimerhandler", "mainloop", "dooneevent" and "quit" have been deprecated -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:36:48 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:36:48 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fix_a_couple_t?= =?utf-8?q?ypos_in_Misc/NEWS=2E?= Message-ID: <3Xv9Q80rKvzRJg@mail.python.org> http://hg.python.org/cpython/rev/62c093909265 changeset: 80213:62c093909265 branch: 3.2 parent: 80209:8f00af8abaf9 user: Ezio Melotti date: Sat Nov 03 21:30:32 2012 +0200 summary: Fix a couple typos in Misc/NEWS. 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 @@ -72,7 +72,7 @@ - Issue #15897: zipimport.c doesn't check return value of fseek(). Patch by Felipe Cruz. -- Issue #15033: Fix the exit status bug when modules invoked using -m swith, +- Issue #15033: Fix the exit status bug when modules invoked using -m switch, return the proper failure return value (1). Patch contributed by Jeff Knupp. - Issue #12268: File readline, readlines and read() or readall() methods @@ -700,7 +700,7 @@ - Issue #15444: Use proper spelling for non-ASCII contributor names. Patch by Serhiy Storchaka. -- Issue 15482: Properly document the default 'level' value for __import__() +- Issue #15482: Properly document the default 'level' value for __import__() while warning about using negative values. - Issue #15230: Clearly document some of the limitations of the runpy -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:36:49 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:36:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_typo_fixes_with_3=2E2=2E?= Message-ID: <3Xv9Q933kRzRJl@mail.python.org> http://hg.python.org/cpython/rev/e6d0951f412a changeset: 80214:e6d0951f412a branch: 3.3 parent: 80210:06577f6b1c99 parent: 80213:62c093909265 user: Ezio Melotti date: Sat Nov 03 21:32:55 2012 +0200 summary: Merge typo fixes with 3.2. files: Misc/NEWS | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -581,14 +581,14 @@ - Issue #15897: zipimport.c doesn't check return value of fseek(). Patch by Felipe Cruz. -- Issue #15033: Fix the exit status bug when modules invoked using -m swith, +- Issue #15033: Fix the exit status bug when modules invoked using -m switch, return the proper failure return value (1). Patch contributed by Jeff Knupp. - Issue #15229: An `OSError` subclass whose __init__ doesn't call back OSError.__init__ could produce incomplete instances, leading to crashes when calling str() on them. -- Issue 15307: Virtual environments now use symlinks with framework builds on +- Issue #15307: Virtual environments now use symlinks with framework builds on Mac OS X, like other POSIX builds. Library @@ -742,7 +742,7 @@ renamed over the old file when flush() is called on an mbox, MMDF or Babyl mailbox. -- Issue 10924: Fixed `crypt.mksalt()` to use a RNG that is suitable for +- Issue #10924: Fixed `crypt.mksalt()` to use a RNG that is suitable for cryptographic purpose. - Issue #15184: Ensure consistent results of OS X configuration tailoring for -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 20:36:50 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 20:36:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_typo_fixes_=28and_the_fix_for_=238401_that_I_wrong?= =?utf-8?q?ly_merged=29_with_3=2E3=2E?= Message-ID: <3Xv9QB5Lh7zRJN@mail.python.org> http://hg.python.org/cpython/rev/a7ebc0db5c18 changeset: 80215:a7ebc0db5c18 parent: 80211:db40752c6cc7 parent: 80214:e6d0951f412a user: Ezio Melotti date: Sat Nov 03 21:36:22 2012 +0200 summary: Merge typo fixes (and the fix for #8401 that I wrongly merged) with 3.3. files: Misc/NEWS | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -673,14 +673,14 @@ - Issue #15897: zipimport.c doesn't check return value of fseek(). Patch by Felipe Cruz. -- Issue #15033: Fix the exit status bug when modules invoked using -m swith, +- Issue #15033: Fix the exit status bug when modules invoked using -m switch, return the proper failure return value (1). Patch contributed by Jeff Knupp. - Issue #15229: An `OSError` subclass whose __init__ doesn't call back OSError.__init__ could produce incomplete instances, leading to crashes when calling str() on them. -- Issue 15307: Virtual environments now use symlinks with framework builds on +- Issue #15307: Virtual environments now use symlinks with framework builds on Mac OS X, like other POSIX builds. Library @@ -834,7 +834,7 @@ renamed over the old file when flush() is called on an mbox, MMDF or Babyl mailbox. -- Issue 10924: Fixed `crypt.mksalt()` to use a RNG that is suitable for +- Issue #10924: Fixed `crypt.mksalt()` to use a RNG that is suitable for cryptographic purpose. - Issue #15184: Ensure consistent results of OS X configuration tailoring for -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:05:31 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 22:05:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE2MzM2OiBmaXgg?= =?utf-8?q?input_checking_in_the_surrogatepass_error_handler=2E__Patch_by_?= =?utf-8?q?Serhiy?= Message-ID: <3XvCNW6m4MzPjt@mail.python.org> http://hg.python.org/cpython/rev/18ed608ee594 changeset: 80216:18ed608ee594 branch: 3.2 parent: 80213:62c093909265 user: Ezio Melotti date: Sat Nov 03 23:03:39 2012 +0200 summary: #16336: fix input checking in the surrogatepass error handler. Patch by Serhiy Storchaka. files: Lib/test/test_codecs.py | 2 ++ Misc/NEWS | 3 +++ Python/codecs.c | 8 ++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -647,6 +647,8 @@ self.assertTrue(codecs.lookup_error("surrogatepass")) with self.assertRaises(UnicodeDecodeError): b"abc\xed\xa0".decode("utf-8", "surrogatepass") + with self.assertRaises(UnicodeDecodeError): + b"abc\xed\xa0z".decode("utf-8", "surrogatepass") class UTF7Test(ReadTest): encoding = "utf-7" diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #16336: fix input checking in the surrogatepass error handler. + Patch by Serhiy Storchaka. + - Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now raises an error. diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -821,10 +821,10 @@ /* Try decoding a single surrogate character. If there are more, let the codec call us again. */ p += start; - if (strlen(p) > 2 && - ((p[0] & 0xf0) == 0xe0 || - (p[1] & 0xc0) == 0x80 || - (p[2] & 0xc0) == 0x80)) { + if (PyBytes_GET_SIZE(object) - start >= 3 && + (p[0] & 0xf0) == 0xe0 && + (p[1] & 0xc0) == 0x80 && + (p[2] & 0xc0) == 0x80) { /* it's a three-byte code */ ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f); if (ch < 0xd800 || ch > 0xdfff) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:05:33 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 22:05:33 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2316336=3A_merge_with_3=2E2=2E?= Message-ID: <3XvCNY2FpWzRC3@mail.python.org> http://hg.python.org/cpython/rev/8d5c147f030d changeset: 80217:8d5c147f030d branch: 3.3 parent: 80214:e6d0951f412a parent: 80216:18ed608ee594 user: Ezio Melotti date: Sat Nov 03 23:04:41 2012 +0200 summary: #16336: merge with 3.2. files: Lib/test/test_codecs.py | 2 ++ Misc/NEWS | 3 +++ Python/codecs.c | 8 ++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -668,6 +668,8 @@ self.assertTrue(codecs.lookup_error("surrogatepass")) with self.assertRaises(UnicodeDecodeError): b"abc\xed\xa0".decode("utf-8", "surrogatepass") + with self.assertRaises(UnicodeDecodeError): + b"abc\xed\xa0z".decode("utf-8", "surrogatepass") @unittest.skipUnless(sys.platform == 'win32', 'cp65001 is a Windows-only codec') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #16336: fix input checking in the surrogatepass error handler. + Patch by Serhiy Storchaka. + - Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now raises an error. diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -791,10 +791,10 @@ /* Try decoding a single surrogate character. If there are more, let the codec call us again. */ p += start; - if (strlen(p) > 2 && - ((p[0] & 0xf0) == 0xe0 || - (p[1] & 0xc0) == 0x80 || - (p[2] & 0xc0) == 0x80)) { + if (PyBytes_GET_SIZE(object) - start >= 3 && + (p[0] & 0xf0) == 0xe0 && + (p[1] & 0xc0) == 0x80 && + (p[2] & 0xc0) == 0x80) { /* it's a three-byte code */ ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f); if (ch < 0xd800 || ch > 0xdfff) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:05:34 2012 From: python-checkins at python.org (ezio.melotti) Date: Sat, 3 Nov 2012 22:05:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE2MzM2OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3XvCNZ4SGnzRCq@mail.python.org> http://hg.python.org/cpython/rev/e4aedd239e45 changeset: 80218:e4aedd239e45 parent: 80215:a7ebc0db5c18 parent: 80217:8d5c147f030d user: Ezio Melotti date: Sat Nov 03 23:05:18 2012 +0200 summary: #16336: merge with 3.3. files: Lib/test/test_codecs.py | 2 ++ Misc/NEWS | 3 +++ Python/codecs.c | 8 ++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -668,6 +668,8 @@ self.assertTrue(codecs.lookup_error("surrogatepass")) with self.assertRaises(UnicodeDecodeError): b"abc\xed\xa0".decode("utf-8", "surrogatepass") + with self.assertRaises(UnicodeDecodeError): + b"abc\xed\xa0z".decode("utf-8", "surrogatepass") @unittest.skipUnless(sys.platform == 'win32', 'cp65001 is a Windows-only codec') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #16336: fix input checking in the surrogatepass error handler. + Patch by Serhiy Storchaka. + - Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now raises an error. diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -791,10 +791,10 @@ /* Try decoding a single surrogate character. If there are more, let the codec call us again. */ p += start; - if (strlen(p) > 2 && - ((p[0] & 0xf0) == 0xe0 || - (p[1] & 0xc0) == 0x80 || - (p[2] & 0xc0) == 0x80)) { + if (PyBytes_GET_SIZE(object) - start >= 3 && + (p[0] & 0xf0) == 0xe0 && + (p[1] & 0xc0) == 0x80 && + (p[2] & 0xc0) == 0x80) { /* it's a three-byte code */ ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f); if (!Py_UNICODE_IS_SURROGATE(ch)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:10:11 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 3 Nov 2012 22:10:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Add_examples_f?= =?utf-8?q?or_opener_argument_of_open_=28=2313424=29=2E?= Message-ID: <3XvCTv2Q38zPjt@mail.python.org> http://hg.python.org/cpython/rev/17b094c08600 changeset: 80219:17b094c08600 branch: 3.3 parent: 80214:e6d0951f412a user: ?ric Araujo date: Sat Nov 03 17:06:52 2012 -0400 summary: Add examples for opener argument of open (#13424). Patch by Guillaume Pratte. files: Doc/library/functions.rst | 30 +++++++++++++++++++++++++++ Doc/library/io.rst | 3 ++ Misc/ACKS | 1 + 3 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -935,6 +935,36 @@ :mod:`os.open` as *opener* results in functionality similar to passing ``None``). + The following example is an alternative implementation for opening files + for exclusive writing. If we did not have support for the ``'x'`` mode, + we could implement it with this opener:: + + >>> import os + >>> def open_exclusive(path, mode): + ... return os.open(path, mode | os.O_CREAT | os.O_EXCL) + ... + >>> filename = 'spam.txt' + >>> fp = open(filename, 'w', opener=open_exclusive) + >>> fp2 = open(filename, 'w', opener=open_exclusive) + Traceback (most recent call last): + ... + FileExistsError: [Errno 17] File exists: 'spam.txt' + + This other example uses the :ref:`dir_fd` parameter of the + :func:`os.open` function to open a file relative to a given directory:: + + >>> import os + >>> def open_relative(dirname): + ... dir_fd = os.open(dirname, os.O_RDONLY) + ... def opener(path, flags): + ... return os.open(path, flags, dir_fd=dir_fd) + ... return opener + ... + >>> opener = open_relative('somedir') + >>> with open('spamspam.txt', 'w', opener=opener) as f: + ... print('This will be written to somedir/spamspam.txt', file=f) + ... + .. versionchanged:: 3.3 The *opener* parameter was added. The ``'x'`` mode was added. diff --git a/Doc/library/io.rst b/Doc/library/io.rst --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -498,6 +498,9 @@ :mod:`os.open` as *opener* results in functionality similar to passing ``None``). + See the :func:`open` built-in function for examples on using the *opener* + parameter. + .. versionchanged:: 3.3 The *opener* parameter was added. The ``'x'`` mode was added. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -929,6 +929,7 @@ Iustin Pop Claudiu Popa John Popplewell +Guillaume Pratte Amrit Prem Paul Prescod Donovan Preston -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:10:12 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 3 Nov 2012 22:10:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4z?= Message-ID: <3XvCTw4jH1zMMp@mail.python.org> http://hg.python.org/cpython/rev/458bf8dffe83 changeset: 80220:458bf8dffe83 parent: 80215:a7ebc0db5c18 parent: 80219:17b094c08600 user: ?ric Araujo date: Sat Nov 03 17:07:40 2012 -0400 summary: Merge 3.3 files: Doc/library/functions.rst | 30 +++++++++++++++++++++++++++ Doc/library/io.rst | 3 ++ Misc/ACKS | 1 + 3 files changed, 34 insertions(+), 0 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -935,6 +935,36 @@ :mod:`os.open` as *opener* results in functionality similar to passing ``None``). + The following example is an alternative implementation for opening files + for exclusive writing. If we did not have support for the ``'x'`` mode, + we could implement it with this opener:: + + >>> import os + >>> def open_exclusive(path, mode): + ... return os.open(path, mode | os.O_CREAT | os.O_EXCL) + ... + >>> filename = 'spam.txt' + >>> fp = open(filename, 'w', opener=open_exclusive) + >>> fp2 = open(filename, 'w', opener=open_exclusive) + Traceback (most recent call last): + ... + FileExistsError: [Errno 17] File exists: 'spam.txt' + + This other example uses the :ref:`dir_fd` parameter of the + :func:`os.open` function to open a file relative to a given directory:: + + >>> import os + >>> def open_relative(dirname): + ... dir_fd = os.open(dirname, os.O_RDONLY) + ... def opener(path, flags): + ... return os.open(path, flags, dir_fd=dir_fd) + ... return opener + ... + >>> opener = open_relative('somedir') + >>> with open('spamspam.txt', 'w', opener=opener) as f: + ... print('This will be written to somedir/spamspam.txt', file=f) + ... + .. versionchanged:: 3.3 The *opener* parameter was added. The ``'x'`` mode was added. diff --git a/Doc/library/io.rst b/Doc/library/io.rst --- a/Doc/library/io.rst +++ b/Doc/library/io.rst @@ -498,6 +498,9 @@ :mod:`os.open` as *opener* results in functionality similar to passing ``None``). + See the :func:`open` built-in function for examples on using the *opener* + parameter. + .. versionchanged:: 3.3 The *opener* parameter was added. The ``'x'`` mode was added. diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -931,6 +931,7 @@ Iustin Pop Claudiu Popa John Popplewell +Guillaume Pratte Amrit Prem Paul Prescod Donovan Preston -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:10:14 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 3 Nov 2012 22:10:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4zIC0+IDMuMyk6?= =?utf-8?q?_Branch_merge?= Message-ID: <3XvCTy078mzRD3@mail.python.org> http://hg.python.org/cpython/rev/dc3791b502ea changeset: 80221:dc3791b502ea branch: 3.3 parent: 80219:17b094c08600 parent: 80217:8d5c147f030d user: ?ric Araujo date: Sat Nov 03 17:09:22 2012 -0400 summary: Branch merge files: Lib/test/test_codecs.py | 2 ++ Misc/NEWS | 3 +++ Python/codecs.c | 8 ++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -668,6 +668,8 @@ self.assertTrue(codecs.lookup_error("surrogatepass")) with self.assertRaises(UnicodeDecodeError): b"abc\xed\xa0".decode("utf-8", "surrogatepass") + with self.assertRaises(UnicodeDecodeError): + b"abc\xed\xa0z".decode("utf-8", "surrogatepass") @unittest.skipUnless(sys.platform == 'win32', 'cp65001 is a Windows-only codec') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #16336: fix input checking in the surrogatepass error handler. + Patch by Serhiy Storchaka. + - Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now raises an error. diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -791,10 +791,10 @@ /* Try decoding a single surrogate character. If there are more, let the codec call us again. */ p += start; - if (strlen(p) > 2 && - ((p[0] & 0xf0) == 0xe0 || - (p[1] & 0xc0) == 0x80 || - (p[2] & 0xc0) == 0x80)) { + if (PyBytes_GET_SIZE(object) - start >= 3 && + (p[0] & 0xf0) == 0xe0 && + (p[1] & 0xc0) == 0x80 && + (p[2] & 0xc0) == 0x80) { /* it's a three-byte code */ ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f); if (ch < 0xd800 || ch > 0xdfff) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:10:15 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 3 Nov 2012 22:10:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Branch_merge?= Message-ID: <3XvCTz2T2gzRCQ@mail.python.org> http://hg.python.org/cpython/rev/2a58d406e5c5 changeset: 80222:2a58d406e5c5 parent: 80220:458bf8dffe83 parent: 80218:e4aedd239e45 user: ?ric Araujo date: Sat Nov 03 17:09:37 2012 -0400 summary: Branch merge files: Lib/test/test_codecs.py | 2 ++ Misc/NEWS | 3 +++ Python/codecs.c | 8 ++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_codecs.py b/Lib/test/test_codecs.py --- a/Lib/test/test_codecs.py +++ b/Lib/test/test_codecs.py @@ -668,6 +668,8 @@ self.assertTrue(codecs.lookup_error("surrogatepass")) with self.assertRaises(UnicodeDecodeError): b"abc\xed\xa0".decode("utf-8", "surrogatepass") + with self.assertRaises(UnicodeDecodeError): + b"abc\xed\xa0z".decode("utf-8", "surrogatepass") @unittest.skipUnless(sys.platform == 'win32', 'cp65001 is a Windows-only codec') diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #16336: fix input checking in the surrogatepass error handler. + Patch by Serhiy Storchaka. + - Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now raises an error. diff --git a/Python/codecs.c b/Python/codecs.c --- a/Python/codecs.c +++ b/Python/codecs.c @@ -791,10 +791,10 @@ /* Try decoding a single surrogate character. If there are more, let the codec call us again. */ p += start; - if (strlen(p) > 2 && - ((p[0] & 0xf0) == 0xe0 || - (p[1] & 0xc0) == 0x80 || - (p[2] & 0xc0) == 0x80)) { + if (PyBytes_GET_SIZE(object) - start >= 3 && + (p[0] & 0xf0) == 0xe0 && + (p[1] & 0xc0) == 0x80 && + (p[2] & 0xc0) == 0x80) { /* it's a three-byte code */ ch = ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + (p[2] & 0x3f); if (!Py_UNICODE_IS_SURROGATE(ch)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:10:16 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 3 Nov 2012 22:10:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Branch_merge?= Message-ID: <3XvCV04VGDzRFs@mail.python.org> http://hg.python.org/cpython/rev/e3f01a6604c8 changeset: 80223:e3f01a6604c8 parent: 80222:2a58d406e5c5 parent: 80221:dc3791b502ea user: ?ric Araujo date: Sat Nov 03 17:10:01 2012 -0400 summary: Branch merge files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:40:18 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 3 Nov 2012 22:40:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Avoid_fd_leak_?= =?utf-8?q?in_example=2E__Caught_by_Serhiy=2E?= Message-ID: <3XvD8f3mRzzMXy@mail.python.org> http://hg.python.org/cpython/rev/95ea024f0569 changeset: 80224:95ea024f0569 branch: 3.3 parent: 80221:dc3791b502ea user: ?ric Araujo date: Sat Nov 03 17:39:45 2012 -0400 summary: Avoid fd leak in example. Caught by Serhiy. files: Doc/library/functions.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -958,12 +958,13 @@ ... dir_fd = os.open(dirname, os.O_RDONLY) ... def opener(path, flags): ... return os.open(path, flags, dir_fd=dir_fd) - ... return opener + ... return opener, dir_fd ... - >>> opener = open_relative('somedir') + >>> opener, dir_fd = open_relative('somedir') >>> with open('spamspam.txt', 'w', opener=opener) as f: ... print('This will be written to somedir/spamspam.txt', file=f) ... + >>> os.close(dir_fd) # don't leak a file descriptor .. versionchanged:: 3.3 The *opener* parameter was added. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 22:40:19 2012 From: python-checkins at python.org (eric.araujo) Date: Sat, 3 Nov 2012 22:40:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4z?= Message-ID: <3XvD8g6JTmzRFs@mail.python.org> http://hg.python.org/cpython/rev/bc8e6301cfc2 changeset: 80225:bc8e6301cfc2 parent: 80223:e3f01a6604c8 parent: 80224:95ea024f0569 user: ?ric Araujo date: Sat Nov 03 17:40:06 2012 -0400 summary: Merge 3.3 files: Doc/library/functions.rst | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst --- a/Doc/library/functions.rst +++ b/Doc/library/functions.rst @@ -958,12 +958,13 @@ ... dir_fd = os.open(dirname, os.O_RDONLY) ... def opener(path, flags): ... return os.open(path, flags, dir_fd=dir_fd) - ... return opener + ... return opener, dir_fd ... - >>> opener = open_relative('somedir') + >>> opener, dir_fd = open_relative('somedir') >>> with open('spamspam.txt', 'w', opener=opener) as f: ... print('This will be written to somedir/spamspam.txt', file=f) ... + >>> os.close(dir_fd) # don't leak a file descriptor .. versionchanged:: 3.3 The *opener* parameter was added. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 23:09:23 2012 From: python-checkins at python.org (christian.heimes) Date: Sat, 3 Nov 2012 23:09:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Fix_compilatio?= =?utf-8?q?n_on_Windows?= Message-ID: <3XvDpC3qWwzN9l@mail.python.org> http://hg.python.org/cpython/rev/d8c47e199297 changeset: 80226:d8c47e199297 branch: 3.2 parent: 80216:18ed608ee594 user: Christian Heimes date: Sat Nov 03 23:07:59 2012 +0100 summary: Fix compilation on Windows files: Objects/bytearrayobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -589,6 +589,7 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + int err; if (PyNumber_Check(values) || PyUnicode_Check(values)) { PyErr_SetString(PyExc_TypeError, "can assign only bytes, buffers, or iterables " @@ -596,7 +597,6 @@ return -1; } /* Make a copy and call this function recursively */ - int err; values = PyByteArray_FromObject(values); if (values == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 23:09:24 2012 From: python-checkins at python.org (christian.heimes) Date: Sat, 3 Nov 2012 23:09:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Fix_compilation_on_Windows?= Message-ID: <3XvDpD62TbzN9l@mail.python.org> http://hg.python.org/cpython/rev/c69f9dcae45b changeset: 80227:c69f9dcae45b branch: 3.3 parent: 80224:95ea024f0569 parent: 80226:d8c47e199297 user: Christian Heimes date: Sat Nov 03 23:08:18 2012 +0100 summary: Fix compilation on Windows files: Objects/bytearrayobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -589,6 +589,7 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + int err; if (PyNumber_Check(values) || PyUnicode_Check(values)) { PyErr_SetString(PyExc_TypeError, "can assign only bytes, buffers, or iterables " @@ -596,7 +597,6 @@ return -1; } /* Make a copy and call this function recursively */ - int err; values = PyByteArray_FromObject(values); if (values == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 23:09:26 2012 From: python-checkins at python.org (christian.heimes) Date: Sat, 3 Nov 2012 23:09:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Fix_compilation_on_Windows?= Message-ID: <3XvDpG1J4ZzP3k@mail.python.org> http://hg.python.org/cpython/rev/23e2682a2096 changeset: 80228:23e2682a2096 parent: 80225:bc8e6301cfc2 parent: 80227:c69f9dcae45b user: Christian Heimes date: Sat Nov 03 23:08:27 2012 +0100 summary: Fix compilation on Windows files: Objects/bytearrayobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -589,6 +589,7 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + int err; if (PyNumber_Check(values) || PyUnicode_Check(values)) { PyErr_SetString(PyExc_TypeError, "can assign only bytes, buffers, or iterables " @@ -596,7 +597,6 @@ return -1; } /* Make a copy and call this function recursively */ - int err; values = PyByteArray_FromObject(values); if (values == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sat Nov 3 23:09:27 2012 From: python-checkins at python.org (christian.heimes) Date: Sat, 3 Nov 2012 23:09:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=282=2E7=29=3A_Fix_compilatio?= =?utf-8?q?n_on_Windows?= Message-ID: <3XvDpH3P4lzPxC@mail.python.org> http://hg.python.org/cpython/rev/6c639a1ff53d changeset: 80229:6c639a1ff53d branch: 2.7 parent: 80212:23b21deef18f user: Christian Heimes date: Sat Nov 03 23:07:59 2012 +0100 summary: Fix compilation on Windows files: Objects/bytearrayobject.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/bytearrayobject.c b/Objects/bytearrayobject.c --- a/Objects/bytearrayobject.c +++ b/Objects/bytearrayobject.c @@ -636,6 +636,7 @@ needed = 0; } else if (values == (PyObject *)self || !PyByteArray_Check(values)) { + int err; if (PyNumber_Check(values) || PyUnicode_Check(values)) { PyErr_SetString(PyExc_TypeError, "can assign only bytes, buffers, or iterables " @@ -643,7 +644,6 @@ return -1; } /* Make a copy and call this function recursively */ - int err; values = PyByteArray_FromObject(values); if (values == NULL) return -1; -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 02:11:07 2012 From: python-checkins at python.org (antoine.pitrou) Date: Sun, 4 Nov 2012 02:11:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315837=3A_add_some?= =?utf-8?q?_tests_for_random=2Eshuffle=28=29=2E?= Message-ID: <3XvJqv654PzR7S@mail.python.org> http://hg.python.org/cpython/rev/58776cc74e89 changeset: 80230:58776cc74e89 parent: 80228:23e2682a2096 user: Antoine Pitrou date: Sun Nov 04 02:10:33 2012 +0100 summary: Issue #15837: add some tests for random.shuffle(). Patch by Alessandro Moura. files: Lib/random.py | 7 +++-- Lib/test/test_random.py | 33 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/Lib/random.py b/Lib/random.py --- a/Lib/random.py +++ b/Lib/random.py @@ -252,10 +252,11 @@ return seq[i] def shuffle(self, x, random=None, int=int): - """x, random=random.random -> shuffle list x in place; return None. + """Shuffle list x in place, and return None. - Optional arg random is a 0-argument function returning a random - float in [0.0, 1.0); by default, the standard random.random. + Optional argument random is a 0-argument function returning a + random float in [0.0, 1.0); if it is the default None, the + standard random.random will be used. """ randbelow = self._randbelow diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -46,6 +46,39 @@ self.assertRaises(TypeError, self.gen.seed, 1, 2, 3, 4) self.assertRaises(TypeError, type(self.gen), []) + def test_shuffle(self): + shuffle = self.gen.shuffle + lst = [] + shuffle(lst) + self.assertEqual(lst, []) + lst = [37] + shuffle(lst) + self.assertEqual(lst, [37]) + seqs = [list(range(n)) for n in range(10)] + shuffled_seqs = [list(range(n)) for n in range(10)] + for shuffled_seq in shuffled_seqs: + shuffle(shuffled_seq) + for (seq, shuffled_seq) in zip(seqs, shuffled_seqs): + self.assertEqual(len(seq), len(shuffled_seq)) + self.assertEqual(set(seq), set(shuffled_seq)) + + # The above tests all would pass if the shuffle was a + # no-op. The following non-deterministic test covers that. It + # asserts that the shuffled sequence of 1000 distinct elements + # must be different from the original one. Although there is + # mathematically a non-zero probability that this could + # actually happen in a genuinely random shuffle, it is + # completely negligible, given that the number of possible + # permutations of 1000 objects is 1000! (factorial of 1000), + # which is considerably larger than the number of atoms in the + # universe... + lst = list(range(1000)) + shuffled_lst = list(range(1000)) + shuffle(shuffled_lst) + self.assertTrue(lst != shuffled_lst) + shuffle(lst) + self.assertTrue(lst != shuffled_lst) + def test_choice(self): choice = self.gen.choice with self.assertRaises(IndexError): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 02:33:45 2012 From: python-checkins at python.org (jesus.cea) Date: Sun, 4 Nov 2012 02:33:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogQ2xvc2VzICMxNjE4?= =?utf-8?q?3=3A_ZipExtFile_object_close_without_file_handle_closed_=28back?= =?utf-8?q?porting?= Message-ID: <3XvKL11f3bzR9h@mail.python.org> http://hg.python.org/cpython/rev/6a14f692df1c changeset: 80231:6a14f692df1c branch: 2.7 parent: 80229:6c639a1ff53d user: Jesus Cea date: Sun Nov 04 02:32:08 2012 +0100 summary: Closes #16183: ZipExtFile object close without file handle closed (backporting of Issue #9846) files: Lib/zipfile.py | 15 +++++++++++++-- 1 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Lib/zipfile.py b/Lib/zipfile.py --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -475,9 +475,11 @@ # Search for universal newlines or line chunks. PATTERN = re.compile(r'^(?P[^\r\n]+)|(?P\n|\r\n?)') - def __init__(self, fileobj, mode, zipinfo, decrypter=None): + def __init__(self, fileobj, mode, zipinfo, decrypter=None, + close_fileobj=False): self._fileobj = fileobj self._decrypter = decrypter + self._close_fileobj = close_fileobj self._compress_type = zipinfo.compress_type self._compress_size = zipinfo.compress_size @@ -649,6 +651,12 @@ self._offset += len(data) return data + def close(self): + try : + if self._close_fileobj: + self._fileobj.close() + finally: + super(ZipExtFile, self).close() class ZipFile(object): @@ -896,8 +904,10 @@ # given a file object in the constructor if self._filePassed: zef_file = self.fp + should_close = False else: zef_file = open(self.filename, 'rb') + should_close = True # Make sure we have an info object if isinstance(name, ZipInfo): @@ -951,7 +961,8 @@ if ord(h[11]) != check_byte: raise RuntimeError("Bad password for file", name) - return ZipExtFile(zef_file, mode, zinfo, zd) + return ZipExtFile(zef_file, mode, zinfo, zd, + close_fileobj=should_close) def extract(self, member, path=None, pwd=None): """Extract a member from the archive to the current working directory, -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Sun Nov 4 05:54:56 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Sun, 04 Nov 2012 05:54:56 +0100 Subject: [Python-checkins] Daily reference leaks (58776cc74e89): sum=1 Message-ID: results for 58776cc74e89 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/reflogQcTjlw', '-x'] From python-checkins at python.org Sun Nov 4 06:00:19 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 06:00:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE2MzA0OiBjbGFy?= =?utf-8?q?ify_match_objects_docs=2E__Initial_patch_by_Jan_Duzinkiewicz=2E?= Message-ID: <3XvPwM214szR7r@mail.python.org> http://hg.python.org/cpython/rev/dc96df8556d8 changeset: 80232:dc96df8556d8 branch: 2.7 user: Ezio Melotti date: Sun Nov 04 06:46:28 2012 +0200 summary: #16304: clarify match objects docs. Initial patch by Jan Duzinkiewicz. files: Doc/library/re.rst | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -797,9 +797,16 @@ .. class:: MatchObject - Match Objects always have a boolean value of :const:`True`, so that you can test - whether e.g. :func:`match` resulted in a match with a simple if statement. They - support the following methods and attributes: + Match objects always have a boolean value of ``True``. + Since :meth:`~regex.match` and :meth:`~regex.search` return ``None`` + when there is no match, you can test whether there was a match with a simple + ``if`` statement:: + + match = re.search(pattern, string) + if match: + process(match) + + Match objects support the following methods and attributes: .. method:: MatchObject.expand(template) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 06:00:20 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 06:00:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE2MzA0OiBjbGFy?= =?utf-8?q?ify_match_objects_docs=2E__Initial_patch_by_Jan_Duzinkiewicz=2E?= Message-ID: <3XvPwN4PCFzRG5@mail.python.org> http://hg.python.org/cpython/rev/1805fc284201 changeset: 80233:1805fc284201 branch: 3.2 parent: 80226:d8c47e199297 user: Ezio Melotti date: Sun Nov 04 06:59:22 2012 +0200 summary: #16304: clarify match objects docs. Initial patch by Jan Duzinkiewicz. files: Doc/library/re.rst | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -814,9 +814,16 @@ Match Objects ------------- -Match objects always have a boolean value of :const:`True`. This lets you -use a simple if-statement to test whether a match was found. Match objects -support the following methods and attributes: +Match objects always have a boolean value of ``True``. +Since :meth:`~regex.match` and :meth:`~regex.search` return ``None`` +when there is no match, you can test whether there was a match with a simple +``if`` statement:: + + match = re.search(pattern, string) + if match: + process(match) + +Match objects support the following methods and attributes: .. method:: match.expand(template) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 06:00:21 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 06:00:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2316304=3A_merge_with_3=2E2=2E?= Message-ID: <3XvPwP6VnmzRHf@mail.python.org> http://hg.python.org/cpython/rev/7fde4b4f7e56 changeset: 80234:7fde4b4f7e56 branch: 3.3 parent: 80227:c69f9dcae45b parent: 80233:1805fc284201 user: Ezio Melotti date: Sun Nov 04 06:59:51 2012 +0200 summary: #16304: merge with 3.2. files: Doc/library/re.rst | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -824,9 +824,16 @@ Match Objects ------------- -Match objects always have a boolean value of :const:`True`. This lets you -use a simple if-statement to test whether a match was found. Match objects -support the following methods and attributes: +Match objects always have a boolean value of ``True``. +Since :meth:`~regex.match` and :meth:`~regex.search` return ``None`` +when there is no match, you can test whether there was a match with a simple +``if`` statement:: + + match = re.search(pattern, string) + if match: + process(match) + +Match objects support the following methods and attributes: .. method:: match.expand(template) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 06:00:23 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 06:00:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE2MzA0OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3XvPwR1QCfzRJ3@mail.python.org> http://hg.python.org/cpython/rev/63b45c959a2a changeset: 80235:63b45c959a2a parent: 80230:58776cc74e89 parent: 80234:7fde4b4f7e56 user: Ezio Melotti date: Sun Nov 04 07:00:04 2012 +0200 summary: #16304: merge with 3.3. files: Doc/library/re.rst | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Doc/library/re.rst b/Doc/library/re.rst --- a/Doc/library/re.rst +++ b/Doc/library/re.rst @@ -824,9 +824,16 @@ Match Objects ------------- -Match objects always have a boolean value of :const:`True`. This lets you -use a simple if-statement to test whether a match was found. Match objects -support the following methods and attributes: +Match objects always have a boolean value of ``True``. +Since :meth:`~regex.match` and :meth:`~regex.search` return ``None`` +when there is no match, you can test whether there was a match with a simple +``if`` statement:: + + match = re.search(pattern, string) + if match: + process(match) + +Match objects support the following methods and attributes: .. method:: match.expand(template) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 12:48:12 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 4 Nov 2012 12:48:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE2NDAy?= =?utf-8?q?=3A_In_range_slicing=2C_fix_shadowing_of_exceptions_from_=5F=5F?= =?utf-8?q?index=5F=5F?= Message-ID: <3XvZz00j0vzRG8@mail.python.org> http://hg.python.org/cpython/rev/94d15358ad6e changeset: 80236:94d15358ad6e branch: 3.2 parent: 80233:1805fc284201 user: Mark Dickinson date: Sun Nov 04 11:46:17 2012 +0000 summary: Issue #16402: In range slicing, fix shadowing of exceptions from __index__ method. files: Lib/test/test_range.py | 9 +++++++++ Misc/NEWS | 3 +++ Objects/rangeobject.c | 10 +++++----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -312,6 +312,15 @@ self.assertRaises(TypeError, range, IN()) + # Test use of user-defined classes in slice indices. + self.assertEqual(list(range(10)[:I(5)]), list(range(5))) + + with self.assertRaises(RuntimeError): + range(0, 10)[:IX()] + + with self.assertRaises(TypeError): + range(0, 10)[:IN()] + def test_count(self): self.assertEqual(range(3).count(-1), 0) self.assertEqual(range(3).count(0), 1) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #16402: When slicing a range, fix shadowing of exceptions from + __index__. + - Issue #16336: fix input checking in the surrogatepass error handler. Patch by Serhiy Storchaka. diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -330,11 +330,11 @@ if (PyIndex_Check(obj)) { result = PyNumber_Index(obj); } - } - if (result == NULL) { - PyErr_SetString(PyExc_TypeError, - "slice indices must be integers or " - "None or have an __index__ method"); + else { + PyErr_SetString(PyExc_TypeError, + "slice indices must be integers or " + "None or have an __index__ method"); + } } return result; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 12:48:13 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 4 Nov 2012 12:48:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2316402=3A_Merge_fix_from_3=2E2?= Message-ID: <3XvZz12shRzRGK@mail.python.org> http://hg.python.org/cpython/rev/2b656a2cf7ef changeset: 80237:2b656a2cf7ef branch: 3.3 parent: 80234:7fde4b4f7e56 parent: 80236:94d15358ad6e user: Mark Dickinson date: Sun Nov 04 11:47:05 2012 +0000 summary: Issue #16402: Merge fix from 3.2 files: Lib/test/test_range.py | 9 +++++++++ Misc/NEWS | 3 +++ Objects/rangeobject.c | 10 +++++----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -312,6 +312,15 @@ self.assertRaises(TypeError, range, IN()) + # Test use of user-defined classes in slice indices. + self.assertEqual(list(range(10)[:I(5)]), list(range(5))) + + with self.assertRaises(RuntimeError): + range(0, 10)[:IX()] + + with self.assertRaises(TypeError): + range(0, 10)[:IN()] + def test_count(self): self.assertEqual(range(3).count(-1), 0) self.assertEqual(range(3).count(0), 1) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #16402: When slicing a range, fix shadowing of exceptions from + __index__. + - Issue #16336: fix input checking in the surrogatepass error handler. Patch by Serhiy Storchaka. diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -331,11 +331,11 @@ if (PyIndex_Check(obj)) { result = PyNumber_Index(obj); } - } - if (result == NULL) { - PyErr_SetString(PyExc_TypeError, - "slice indices must be integers or " - "None or have an __index__ method"); + else { + PyErr_SetString(PyExc_TypeError, + "slice indices must be integers or " + "None or have an __index__ method"); + } } return result; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 12:48:14 2012 From: python-checkins at python.org (mark.dickinson) Date: Sun, 4 Nov 2012 12:48:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316402=3A_Merge_fix_from_3=2E3?= Message-ID: <3XvZz25RbvzRGH@mail.python.org> http://hg.python.org/cpython/rev/f02555353544 changeset: 80238:f02555353544 parent: 80235:63b45c959a2a parent: 80237:2b656a2cf7ef user: Mark Dickinson date: Sun Nov 04 11:47:47 2012 +0000 summary: Issue #16402: Merge fix from 3.3 files: Lib/test/test_range.py | 9 +++++++++ Misc/NEWS | 3 +++ Objects/rangeobject.c | 10 +++++----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py --- a/Lib/test/test_range.py +++ b/Lib/test/test_range.py @@ -312,6 +312,15 @@ self.assertRaises(TypeError, range, IN()) + # Test use of user-defined classes in slice indices. + self.assertEqual(range(10)[:I(5)], range(5)) + + with self.assertRaises(RuntimeError): + range(0, 10)[:IX()] + + with self.assertRaises(TypeError): + range(0, 10)[:IN()] + def test_count(self): self.assertEqual(range(3).count(-1), 0) self.assertEqual(range(3).count(0), 1) diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #16402: When slicing a range, fix shadowing of exceptions from + __index__. + - Issue #16336: fix input checking in the surrogatepass error handler. Patch by Serhiy Storchaka. diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -331,11 +331,11 @@ if (PyIndex_Check(obj)) { result = PyNumber_Index(obj); } - } - if (result == NULL) { - PyErr_SetString(PyExc_TypeError, - "slice indices must be integers or " - "None or have an __index__ method"); + else { + PyErr_SetString(PyExc_TypeError, + "slice indices must be integers or " + "None or have an __index__ method"); + } } return result; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 14:54:23 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 4 Nov 2012 14:54:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzU3NjU6?= =?utf-8?q?_Apply_a_hard_recursion_limit_in_the_compiler?= Message-ID: <3Xvdmb1vqBzRFq@mail.python.org> http://hg.python.org/cpython/rev/ab02cd145f56 changeset: 80239:ab02cd145f56 branch: 3.3 parent: 80237:2b656a2cf7ef user: Nick Coghlan date: Sun Nov 04 23:14:34 2012 +1000 summary: Issue #5765: Apply a hard recursion limit in the compiler Previously, excessive nesting in expressions would blow the stack and segfault the interpreter. Now, a hard limit based on the configured recursion limit and a hardcoded scaling factor is applied. files: Include/symtable.h | 2 + Lib/test/crashers/compiler_recursion.py | 13 - Lib/test/test_compile.py | 27 +++ Misc/ACKS | 1 + Misc/NEWS | 3 + Python/compile.c | 5 + Python/symtable.c | 97 +++++++++--- 7 files changed, 106 insertions(+), 42 deletions(-) diff --git a/Include/symtable.h b/Include/symtable.h --- a/Include/symtable.h +++ b/Include/symtable.h @@ -30,6 +30,8 @@ PyObject *st_private; /* name of current class or NULL */ PyFutureFeatures *st_future; /* module's future features that affect the symbol table */ + int recursion_depth; /* current recursion depth */ + int recursion_limit; /* recursion limit */ }; typedef struct _symtable_entry { diff --git a/Lib/test/crashers/compiler_recursion.py b/Lib/test/crashers/compiler_recursion.py deleted file mode 100644 --- a/Lib/test/crashers/compiler_recursion.py +++ /dev/null @@ -1,13 +0,0 @@ -""" -The compiler (>= 2.5) recurses happily until it blows the stack. - -Recorded on the tracker as http://bugs.python.org/issue11383 -""" - -# The variant below blows up in compiler_call, but there are assorted -# other variations that blow up in other functions -# e.g. '1*'*10**5+'1' will die in compiler_visit_expr - -# The exact limit to destroy the stack will vary by platform -# but 10M should do the trick even with huge stack allocations -compile('()'*10**7, '?', 'exec') diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -474,6 +474,33 @@ self.assertInvalidSingle('f()\nxy # blah\nblah()') self.assertInvalidSingle('x = 5 # comment\nx = 6\n') + @support.cpython_only + def test_compiler_recursion_limit(self): + # Expected limit is sys.getrecursionlimit() * the scaling factor + # in symtable.c (currently 3) + # We expect to fail *at* that limit, because we use up some of + # the stack depth limit in the test suite code + # So we check the expected limit and 75% of that + # XXX (ncoghlan): duplicating the scaling factor here is a little + # ugly. Perhaps it should be exposed somewhere... + fail_depth = sys.getrecursionlimit() * 3 + success_depth = int(fail_depth * 0.75) + + def check_limit(prefix, repeated): + expect_ok = prefix + repeated * success_depth + self.compile_single(expect_ok) + broken = prefix + repeated * fail_depth + details = "Compiling ({!r} + {!r} * {})".format( + prefix, repeated, fail_depth) + with self.assertRaises(RuntimeError, msg=details): + self.compile_single(broken) + + check_limit("a", "()") + check_limit("a", ".b") + check_limit("a", "[0]") + check_limit("a", "*a") + + def test_main(): support.run_unittest(TestSpecifics) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -431,6 +431,7 @@ Nathaniel Gray Eddy De Greef Grant Griffin +Andrea Griffini Duncan Grisby Fabian Groffen Eric Groo diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #5765: Apply a hard recursion limit in the compiler instead of + blowing the stack and segfaulting. + - Issue #16402: When slicing a range, fix shadowing of exceptions from __index__. diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -141,6 +141,11 @@ The u pointer points to the current compilation unit, while units for enclosing blocks are stored in c_stack. The u and c_stack are managed by compiler_enter_scope() and compiler_exit_scope(). + +Note that we don't track recursion levels during compilation - the +task of detecting and rejecting excessive levels of nesting is +handled by the symbol analysis pass. + */ struct compiler { diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -220,17 +220,40 @@ return NULL; } +/* When compiling the use of C stack is probably going to be a lot + lighter than when executing Python code but still can overflow + and causing a Python crash if not checked (e.g. eval("()"*300000)). + Using the current recursion limit for the compiler seems too + restrictive (it caused at least one test to fail) so a factor is + used to allow deeper recursion when compiling an expression. + + Using a scaling factor means this should automatically adjust when + the recursion limit is adjusted for small or large C stack allocations. +*/ +#define COMPILER_STACK_FRAME_SCALE 3 + struct symtable * PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) { struct symtable *st = symtable_new(); asdl_seq *seq; int i; + PyThreadState *tstate; if (st == NULL) return st; st->st_filename = filename; st->st_future = future; + + /* Setup recursion depth check counters */ + tstate = PyThreadState_GET(); + if (!tstate) { + PySymtable_Free(st); + return NULL; + } + st->recursion_depth = tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE; + st->recursion_limit = Py_GetRecursionLimit() * COMPILER_STACK_FRAME_SCALE; + /* Make the initial symbol information gathering pass */ if (!GET_IDENTIFIER(top) || !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0, 0)) { @@ -1013,11 +1036,17 @@ VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is useful if the first node in the sequence requires special treatment. + + VISIT_QUIT macro returns the specified value exiting from the function but + first adjusts current recursion counter depth. */ +#define VISIT_QUIT(ST, X) \ + return --(ST)->recursion_depth,(X) + #define VISIT(ST, TYPE, V) \ if (!symtable_visit_ ## TYPE((ST), (V))) \ - return 0; + VISIT_QUIT((ST), 0); #define VISIT_SEQ(ST, TYPE, SEQ) { \ int i; \ @@ -1025,7 +1054,7 @@ for (i = 0; i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ if (!symtable_visit_ ## TYPE((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1035,7 +1064,7 @@ for (i = (START); i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ if (!symtable_visit_ ## TYPE((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1046,7 +1075,7 @@ expr_ty elt = (expr_ty)asdl_seq_GET(seq, i); \ if (!elt) continue; /* can be NULL */ \ if (!symtable_visit_expr((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1071,32 +1100,37 @@ static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { + if (++st->recursion_depth > st->recursion_limit) { + PyErr_SetString(PyExc_RuntimeError, + "maximum recursion depth exceeded during compilation"); + VISIT_QUIT(st, 0); + } switch (s->kind) { case FunctionDef_kind: if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); if (s->v.FunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); if (s->v.FunctionDef.args->kw_defaults) VISIT_KWONLYDEFAULTS(st, s->v.FunctionDef.args->kw_defaults); if (!symtable_visit_annotations(st, s)) - return 0; + VISIT_QUIT(st, 0); if (s->v.FunctionDef.decorator_list) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, FunctionBlock, (void *)s, s->lineno, s->col_offset)) - return 0; + VISIT_QUIT(st, 0); VISIT(st, arguments, s->v.FunctionDef.args); VISIT_SEQ(st, stmt, s->v.FunctionDef.body); if (!symtable_exit_block(st, s)) - return 0; + VISIT_QUIT(st, 0); break; case ClassDef_kind: { PyObject *tmp; if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); VISIT_SEQ(st, expr, s->v.ClassDef.bases); VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); if (s->v.ClassDef.starargs) @@ -1107,20 +1141,20 @@ VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno, s->col_offset)) - return 0; + VISIT_QUIT(st, 0); if (!GET_IDENTIFIER(__class__) || !symtable_add_def(st, __class__, DEF_LOCAL) || !GET_IDENTIFIER(__locals__) || !symtable_add_def(st, __locals__, DEF_PARAM)) { symtable_exit_block(st, s); - return 0; + VISIT_QUIT(st, 0); } tmp = st->st_private; st->st_private = s->v.ClassDef.name; VISIT_SEQ(st, stmt, s->v.ClassDef.body); st->st_private = tmp; if (!symtable_exit_block(st, s)) - return 0; + VISIT_QUIT(st, 0); break; } case Return_kind: @@ -1204,7 +1238,7 @@ identifier name = (identifier)asdl_seq_GET(seq, i); long cur = symtable_lookup(st, name); if (cur < 0) - return 0; + VISIT_QUIT(st, 0); if (cur & (DEF_LOCAL | USE)) { char buf[256]; char *c_name = _PyUnicode_AsString(name); @@ -1219,10 +1253,10 @@ GLOBAL_AFTER_USE, c_name); if (!symtable_warn(st, buf, s->lineno)) - return 0; + VISIT_QUIT(st, 0); } if (!symtable_add_def(st, name, DEF_GLOBAL)) - return 0; + VISIT_QUIT(st, 0); } break; } @@ -1233,7 +1267,7 @@ identifier name = (identifier)asdl_seq_GET(seq, i); long cur = symtable_lookup(st, name); if (cur < 0) - return 0; + VISIT_QUIT(st, 0); if (cur & (DEF_LOCAL | USE)) { char buf[256]; char *c_name = _PyUnicode_AsString(name); @@ -1248,10 +1282,10 @@ NONLOCAL_AFTER_USE, c_name); if (!symtable_warn(st, buf, s->lineno)) - return 0; + VISIT_QUIT(st, 0); } if (!symtable_add_def(st, name, DEF_NONLOCAL)) - return 0; + VISIT_QUIT(st, 0); } break; } @@ -1268,12 +1302,17 @@ VISIT_SEQ(st, stmt, s->v.With.body); break; } - return 1; + VISIT_QUIT(st, 1); } static int symtable_visit_expr(struct symtable *st, expr_ty e) { + if (++st->recursion_depth > st->recursion_limit) { + PyErr_SetString(PyExc_RuntimeError, + "maximum recursion depth exceeded during compilation"); + VISIT_QUIT(st, 0); + } switch (e->kind) { case BoolOp_kind: VISIT_SEQ(st, expr, e->v.BoolOp.values); @@ -1287,7 +1326,7 @@ break; case Lambda_kind: { if (!GET_IDENTIFIER(lambda)) - return 0; + VISIT_QUIT(st, 0); if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (e->v.Lambda.args->kw_defaults) @@ -1296,11 +1335,11 @@ if (!symtable_enter_block(st, lambda, FunctionBlock, (void *)e, e->lineno, e->col_offset)) - return 0; + VISIT_QUIT(st, 0); VISIT(st, arguments, e->v.Lambda.args); VISIT(st, expr, e->v.Lambda.body); if (!symtable_exit_block(st, (void *)e)) - return 0; + VISIT_QUIT(st, 0); break; } case IfExp_kind: @@ -1317,19 +1356,19 @@ break; case GeneratorExp_kind: if (!symtable_visit_genexp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case ListComp_kind: if (!symtable_visit_listcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case SetComp_kind: if (!symtable_visit_setcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case DictComp_kind: if (!symtable_visit_dictcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case Yield_kind: case YieldFrom_kind: { @@ -1373,14 +1412,14 @@ case Name_kind: if (!symtable_add_def(st, e->v.Name.id, e->v.Name.ctx == Load ? USE : DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); /* Special-case super: it counts as a use of __class__ */ if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { if (!GET_IDENTIFIER(__class__) || !symtable_add_def(st, __class__, USE)) - return 0; + VISIT_QUIT(st, 0); } break; /* child nodes of List and Tuple will have expr_context set */ @@ -1391,7 +1430,7 @@ VISIT_SEQ(st, expr, e->v.Tuple.elts); break; } - return 1; + VISIT_QUIT(st, 1); } static int -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 14:54:24 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 4 Nov 2012 14:54:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=235765=3A_Merge_from_3=2E3?= Message-ID: <3Xvdmc5qthzRFy@mail.python.org> http://hg.python.org/cpython/rev/bd1db93d76e1 changeset: 80240:bd1db93d76e1 parent: 80238:f02555353544 parent: 80239:ab02cd145f56 user: Nick Coghlan date: Sun Nov 04 23:53:15 2012 +1000 summary: Issue #5765: Merge from 3.3 files: Include/symtable.h | 2 + Lib/test/crashers/compiler_recursion.py | 13 - Lib/test/test_compile.py | 27 +++ Misc/ACKS | 1 + Misc/NEWS | 3 + Python/compile.c | 5 + Python/symtable.c | 101 ++++++++--- 7 files changed, 108 insertions(+), 44 deletions(-) diff --git a/Include/symtable.h b/Include/symtable.h --- a/Include/symtable.h +++ b/Include/symtable.h @@ -30,6 +30,8 @@ PyObject *st_private; /* name of current class or NULL */ PyFutureFeatures *st_future; /* module's future features that affect the symbol table */ + int recursion_depth; /* current recursion depth */ + int recursion_limit; /* recursion limit */ }; typedef struct _symtable_entry { diff --git a/Lib/test/crashers/compiler_recursion.py b/Lib/test/crashers/compiler_recursion.py deleted file mode 100644 --- a/Lib/test/crashers/compiler_recursion.py +++ /dev/null @@ -1,13 +0,0 @@ -""" -The compiler (>= 2.5) recurses happily until it blows the stack. - -Recorded on the tracker as http://bugs.python.org/issue11383 -""" - -# The variant below blows up in compiler_call, but there are assorted -# other variations that blow up in other functions -# e.g. '1*'*10**5+'1' will die in compiler_visit_expr - -# The exact limit to destroy the stack will vary by platform -# but 10M should do the trick even with huge stack allocations -compile('()'*10**7, '?', 'exec') diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -474,6 +474,33 @@ self.assertInvalidSingle('f()\nxy # blah\nblah()') self.assertInvalidSingle('x = 5 # comment\nx = 6\n') + @support.cpython_only + def test_compiler_recursion_limit(self): + # Expected limit is sys.getrecursionlimit() * the scaling factor + # in symtable.c (currently 3) + # We expect to fail *at* that limit, because we use up some of + # the stack depth limit in the test suite code + # So we check the expected limit and 75% of that + # XXX (ncoghlan): duplicating the scaling factor here is a little + # ugly. Perhaps it should be exposed somewhere... + fail_depth = sys.getrecursionlimit() * 3 + success_depth = int(fail_depth * 0.75) + + def check_limit(prefix, repeated): + expect_ok = prefix + repeated * success_depth + self.compile_single(expect_ok) + broken = prefix + repeated * fail_depth + details = "Compiling ({!r} + {!r} * {})".format( + prefix, repeated, fail_depth) + with self.assertRaises(RuntimeError, msg=details): + self.compile_single(broken) + + check_limit("a", "()") + check_limit("a", ".b") + check_limit("a", "[0]") + check_limit("a", "*a") + + def test_main(): support.run_unittest(TestSpecifics) diff --git a/Misc/ACKS b/Misc/ACKS --- a/Misc/ACKS +++ b/Misc/ACKS @@ -431,6 +431,7 @@ Nathaniel Gray Eddy De Greef Grant Griffin +Andrea Griffini Duncan Grisby Fabian Groffen Eric Groo diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #5765: Apply a hard recursion limit in the compiler instead of + blowing the stack and segfaulting. + - Issue #16402: When slicing a range, fix shadowing of exceptions from __index__. diff --git a/Python/compile.c b/Python/compile.c --- a/Python/compile.c +++ b/Python/compile.c @@ -141,6 +141,11 @@ The u pointer points to the current compilation unit, while units for enclosing blocks are stored in c_stack. The u and c_stack are managed by compiler_enter_scope() and compiler_exit_scope(). + +Note that we don't track recursion levels during compilation - the +task of detecting and rejecting excessive levels of nesting is +handled by the symbol analysis pass. + */ struct compiler { diff --git a/Python/symtable.c b/Python/symtable.c --- a/Python/symtable.c +++ b/Python/symtable.c @@ -223,17 +223,40 @@ return NULL; } +/* When compiling the use of C stack is probably going to be a lot + lighter than when executing Python code but still can overflow + and causing a Python crash if not checked (e.g. eval("()"*300000)). + Using the current recursion limit for the compiler seems too + restrictive (it caused at least one test to fail) so a factor is + used to allow deeper recursion when compiling an expression. + + Using a scaling factor means this should automatically adjust when + the recursion limit is adjusted for small or large C stack allocations. +*/ +#define COMPILER_STACK_FRAME_SCALE 3 + struct symtable * PySymtable_Build(mod_ty mod, const char *filename, PyFutureFeatures *future) { struct symtable *st = symtable_new(); asdl_seq *seq; int i; + PyThreadState *tstate; if (st == NULL) return st; st->st_filename = filename; st->st_future = future; + + /* Setup recursion depth check counters */ + tstate = PyThreadState_GET(); + if (!tstate) { + PySymtable_Free(st); + return NULL; + } + st->recursion_depth = tstate->recursion_depth * COMPILER_STACK_FRAME_SCALE; + st->recursion_limit = Py_GetRecursionLimit() * COMPILER_STACK_FRAME_SCALE; + /* Make the initial symbol information gathering pass */ if (!GET_IDENTIFIER(top) || !symtable_enter_block(st, top, ModuleBlock, (void *)mod, 0, 0)) { @@ -1031,11 +1054,17 @@ VISIT_SEQ_TAIL permits the start of an ASDL sequence to be skipped, which is useful if the first node in the sequence requires special treatment. + + VISIT_QUIT macro returns the specified value exiting from the function but + first adjusts current recursion counter depth. */ +#define VISIT_QUIT(ST, X) \ + return --(ST)->recursion_depth,(X) + #define VISIT(ST, TYPE, V) \ if (!symtable_visit_ ## TYPE((ST), (V))) \ - return 0; + VISIT_QUIT((ST), 0); #define VISIT_SEQ(ST, TYPE, SEQ) { \ int i; \ @@ -1043,7 +1072,7 @@ for (i = 0; i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ if (!symtable_visit_ ## TYPE((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1053,7 +1082,7 @@ for (i = (START); i < asdl_seq_LEN(seq); i++) { \ TYPE ## _ty elt = (TYPE ## _ty)asdl_seq_GET(seq, i); \ if (!symtable_visit_ ## TYPE((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1064,7 +1093,7 @@ expr_ty elt = (expr_ty)asdl_seq_GET(seq, i); \ if (!elt) continue; /* can be NULL */ \ if (!symtable_visit_expr((ST), elt)) \ - return 0; \ + VISIT_QUIT((ST), 0); \ } \ } @@ -1108,32 +1137,37 @@ static int symtable_visit_stmt(struct symtable *st, stmt_ty s) { + if (++st->recursion_depth > st->recursion_limit) { + PyErr_SetString(PyExc_RuntimeError, + "maximum recursion depth exceeded during compilation"); + VISIT_QUIT(st, 0); + } switch (s->kind) { case FunctionDef_kind: if (!symtable_add_def(st, s->v.FunctionDef.name, DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); if (s->v.FunctionDef.args->defaults) VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults); if (s->v.FunctionDef.args->kw_defaults) VISIT_KWONLYDEFAULTS(st, s->v.FunctionDef.args->kw_defaults); if (!symtable_visit_annotations(st, s)) - return 0; + VISIT_QUIT(st, 0); if (s->v.FunctionDef.decorator_list) VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list); if (!symtable_enter_block(st, s->v.FunctionDef.name, FunctionBlock, (void *)s, s->lineno, s->col_offset)) - return 0; + VISIT_QUIT(st, 0); VISIT(st, arguments, s->v.FunctionDef.args); VISIT_SEQ(st, stmt, s->v.FunctionDef.body); if (!symtable_exit_block(st, s)) - return 0; + VISIT_QUIT(st, 0); break; case ClassDef_kind: { PyObject *tmp; if (!symtable_add_def(st, s->v.ClassDef.name, DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); VISIT_SEQ(st, expr, s->v.ClassDef.bases); VISIT_SEQ(st, keyword, s->v.ClassDef.keywords); if (s->v.ClassDef.starargs) @@ -1144,20 +1178,20 @@ VISIT_SEQ(st, expr, s->v.ClassDef.decorator_list); if (!symtable_enter_block(st, s->v.ClassDef.name, ClassBlock, (void *)s, s->lineno, s->col_offset)) - return 0; + VISIT_QUIT(st, 0); if (!GET_IDENTIFIER(__class__) || !symtable_add_def(st, __class__, DEF_LOCAL) || !GET_IDENTIFIER(__locals__) || !symtable_add_def(st, __locals__, DEF_PARAM)) { symtable_exit_block(st, s); - return 0; + VISIT_QUIT(st, 0); } tmp = st->st_private; st->st_private = s->v.ClassDef.name; VISIT_SEQ(st, stmt, s->v.ClassDef.body); st->st_private = tmp; if (!symtable_exit_block(st, s)) - return 0; + VISIT_QUIT(st, 0); break; } case Return_kind: @@ -1241,7 +1275,7 @@ identifier name = (identifier)asdl_seq_GET(seq, i); long cur = symtable_lookup(st, name); if (cur < 0) - return 0; + VISIT_QUIT(st, 0); if (cur & (DEF_LOCAL | USE)) { char buf[256]; char *c_name = _PyUnicode_AsString(name); @@ -1256,12 +1290,12 @@ GLOBAL_AFTER_USE, c_name); if (!symtable_warn(st, buf, s->lineno)) - return 0; + VISIT_QUIT(st, 0); } if (!symtable_add_def(st, name, DEF_GLOBAL)) - return 0; + VISIT_QUIT(st, 0); if (!symtable_record_directive(st, name, s)) - return 0; + VISIT_QUIT(st, 0); } break; } @@ -1272,7 +1306,7 @@ identifier name = (identifier)asdl_seq_GET(seq, i); long cur = symtable_lookup(st, name); if (cur < 0) - return 0; + VISIT_QUIT(st, 0); if (cur & (DEF_LOCAL | USE)) { char buf[256]; char *c_name = _PyUnicode_AsString(name); @@ -1287,12 +1321,12 @@ NONLOCAL_AFTER_USE, c_name); if (!symtable_warn(st, buf, s->lineno)) - return 0; + VISIT_QUIT(st, 0); } if (!symtable_add_def(st, name, DEF_NONLOCAL)) - return 0; + VISIT_QUIT(st, 0); if (!symtable_record_directive(st, name, s)) - return 0; + VISIT_QUIT(st, 0); } break; } @@ -1309,12 +1343,17 @@ VISIT_SEQ(st, stmt, s->v.With.body); break; } - return 1; + VISIT_QUIT(st, 1); } static int symtable_visit_expr(struct symtable *st, expr_ty e) { + if (++st->recursion_depth > st->recursion_limit) { + PyErr_SetString(PyExc_RuntimeError, + "maximum recursion depth exceeded during compilation"); + VISIT_QUIT(st, 0); + } switch (e->kind) { case BoolOp_kind: VISIT_SEQ(st, expr, e->v.BoolOp.values); @@ -1328,7 +1367,7 @@ break; case Lambda_kind: { if (!GET_IDENTIFIER(lambda)) - return 0; + VISIT_QUIT(st, 0); if (e->v.Lambda.args->defaults) VISIT_SEQ(st, expr, e->v.Lambda.args->defaults); if (e->v.Lambda.args->kw_defaults) @@ -1337,11 +1376,11 @@ if (!symtable_enter_block(st, lambda, FunctionBlock, (void *)e, e->lineno, e->col_offset)) - return 0; + VISIT_QUIT(st, 0); VISIT(st, arguments, e->v.Lambda.args); VISIT(st, expr, e->v.Lambda.body); if (!symtable_exit_block(st, (void *)e)) - return 0; + VISIT_QUIT(st, 0); break; } case IfExp_kind: @@ -1358,19 +1397,19 @@ break; case GeneratorExp_kind: if (!symtable_visit_genexp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case ListComp_kind: if (!symtable_visit_listcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case SetComp_kind: if (!symtable_visit_setcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case DictComp_kind: if (!symtable_visit_dictcomp(st, e)) - return 0; + VISIT_QUIT(st, 0); break; case Yield_kind: case YieldFrom_kind: { @@ -1414,14 +1453,14 @@ case Name_kind: if (!symtable_add_def(st, e->v.Name.id, e->v.Name.ctx == Load ? USE : DEF_LOCAL)) - return 0; + VISIT_QUIT(st, 0); /* Special-case super: it counts as a use of __class__ */ if (e->v.Name.ctx == Load && st->st_cur->ste_type == FunctionBlock && !PyUnicode_CompareWithASCIIString(e->v.Name.id, "super")) { if (!GET_IDENTIFIER(__class__) || !symtable_add_def(st, __class__, USE)) - return 0; + VISIT_QUIT(st, 0); } break; /* child nodes of List and Tuple will have expr_context set */ @@ -1432,7 +1471,7 @@ VISIT_SEQ(st, expr, e->v.Tuple.elts); break; } - return 1; + VISIT_QUIT(st, 1); } static int -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 15:20:02 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 4 Nov 2012 15:20:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzU3NjU6?= =?utf-8?q?_Also_check_the_compiler_when_finding_the_recursion_limit?= Message-ID: <3XvfLB1y4CzMQL@mail.python.org> http://hg.python.org/cpython/rev/cf2515d0328b changeset: 80241:cf2515d0328b branch: 3.3 parent: 80239:ab02cd145f56 user: Nick Coghlan date: Mon Nov 05 00:19:18 2012 +1000 summary: Issue #5765: Also check the compiler when finding the recursion limit files: Tools/scripts/find_recursionlimit.py | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py --- a/Tools/scripts/find_recursionlimit.py +++ b/Tools/scripts/find_recursionlimit.py @@ -89,6 +89,12 @@ _pickle.Pickler(io.BytesIO(), protocol=-1).dump(l) _cache[n] = l +def test_compiler_recursion(): + # The compiler uses a scaling factor to support additional levels + # of recursion. This is a sanity check of that scaling to ensure + # it still throws RuntimeError even at higher recursion limits + compile("()" * (10 * sys.getrecursionlimit()), "", "single") + def check_limit(n, test_func_name): sys.setrecursionlimit(n) if test_func_name.startswith("test_"): @@ -117,5 +123,6 @@ check_limit(limit, "test_getattr") check_limit(limit, "test_getitem") check_limit(limit, "test_cpickle") + check_limit(limit, "test_compiler_recursion") print("Limit of %d is fine" % limit) limit = limit + 100 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 15:20:03 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 4 Nov 2012 15:20:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=235765=3A_Merge_from_3=2E3?= Message-ID: <3XvfLC46gCzRG4@mail.python.org> http://hg.python.org/cpython/rev/3712028a0c34 changeset: 80242:3712028a0c34 parent: 80240:bd1db93d76e1 parent: 80241:cf2515d0328b user: Nick Coghlan date: Mon Nov 05 00:19:49 2012 +1000 summary: Issue #5765: Merge from 3.3 files: Tools/scripts/find_recursionlimit.py | 7 +++++++ 1 files changed, 7 insertions(+), 0 deletions(-) diff --git a/Tools/scripts/find_recursionlimit.py b/Tools/scripts/find_recursionlimit.py --- a/Tools/scripts/find_recursionlimit.py +++ b/Tools/scripts/find_recursionlimit.py @@ -89,6 +89,12 @@ _pickle.Pickler(io.BytesIO(), protocol=-1).dump(l) _cache[n] = l +def test_compiler_recursion(): + # The compiler uses a scaling factor to support additional levels + # of recursion. This is a sanity check of that scaling to ensure + # it still throws RuntimeError even at higher recursion limits + compile("()" * (10 * sys.getrecursionlimit()), "", "single") + def check_limit(n, test_func_name): sys.setrecursionlimit(n) if test_func_name.startswith("test_"): @@ -117,5 +123,6 @@ check_limit(limit, "test_getattr") check_limit(limit, "test_getitem") check_limit(limit, "test_cpickle") + check_limit(limit, "test_compiler_recursion") print("Limit of %d is fine" % limit) limit = limit + 100 -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 15:56:11 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 4 Nov 2012 15:56:11 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Properly_credi?= =?utf-8?q?t_patch?= Message-ID: <3Xvg7v2ws6zRCP@mail.python.org> http://hg.python.org/cpython/rev/549f7b5baa83 changeset: 80243:549f7b5baa83 branch: 3.3 parent: 80241:cf2515d0328b user: Nick Coghlan date: Mon Nov 05 00:55:46 2012 +1000 summary: Properly credit patch 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 @@ -13,7 +13,7 @@ ----------------- - Issue #5765: Apply a hard recursion limit in the compiler instead of - blowing the stack and segfaulting. + blowing the stack and segfaulting. Initial patch by Andrea Griffini. - Issue #16402: When slicing a range, fix shadowing of exceptions from __index__. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 15:56:12 2012 From: python-checkins at python.org (nick.coghlan) Date: Sun, 4 Nov 2012 15:56:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E3?= Message-ID: <3Xvg7w5QzPzRGZ@mail.python.org> http://hg.python.org/cpython/rev/4a9dbd9b152e changeset: 80244:4a9dbd9b152e parent: 80242:3712028a0c34 parent: 80243:549f7b5baa83 user: Nick Coghlan date: Mon Nov 05 00:56:02 2012 +1000 summary: Merge from 3.3 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 @@ -11,7 +11,7 @@ ----------------- - Issue #5765: Apply a hard recursion limit in the compiler instead of - blowing the stack and segfaulting. + blowing the stack and segfaulting. Initial patch by Andrea Griffini. - Issue #16402: When slicing a range, fix shadowing of exceptions from __index__. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 21:05:39 2012 From: python-checkins at python.org (stefan.krah) Date: Sun, 4 Nov 2012 21:05:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Fix_copy=26paste_errors_an?= =?utf-8?q?d_reformulate_the_tests=2E?= Message-ID: <3Xvp0z6jbtzRKJ@mail.python.org> http://hg.python.org/cpython/rev/fc8f1b1c76bf changeset: 80245:fc8f1b1c76bf user: Stefan Krah date: Sun Nov 04 20:53:50 2012 +0100 summary: Fix copy&paste errors and reformulate the tests. files: Lib/test/test_buffer.py | 20 +++++--------------- 1 files changed, 5 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4001,23 +4001,13 @@ # equality-hash invariant x = ndarray(list(range(12)), shape=[12], format='B') - a = memoryview(nd) + a = memoryview(x) y = ndarray(list(range(12)), shape=[12], format='b') - b = memoryview(nd) - - z = ndarray(list(bytes(chr(x), 'latin-1') for x in range(12)), - shape=[12], format='c') - c = memoryview(nd) - - if (a == b): - self.assertEqual(hash(a), hash(b)) - - if (a == c): - self.assertEqual(hash(a), hash(c)) - - if (b == c): - self.assertEqual(hash(b), hash(c)) + b = memoryview(y) + + self.assertEqual(a, b) + self.assertEqual(hash(a), hash(b)) # non-byte formats nd = ndarray(list(range(12)), shape=[2,2,3], format='L') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 22:23:37 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 22:23:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogIzgyNzE6IHRoZSB1?= =?utf-8?q?tf-8_decoder_now_outputs_the_correct_number_of_U+FFFD__characte?= =?utf-8?q?rs?= Message-ID: <3Xvqkx4DnWzRBH@mail.python.org> http://hg.python.org/cpython/rev/5962f192a483 changeset: 80246:5962f192a483 branch: 3.3 parent: 80243:549f7b5baa83 user: Ezio Melotti date: Sun Nov 04 23:21:38 2012 +0200 summary: #8271: the utf-8 decoder now outputs the correct number of U+FFFD characters when used with the "replace" error handler on invalid utf-8 sequences. Patch by Serhiy Storchaka, tests by Ezio Melotti. files: Lib/test/test_unicode.py | 222 ++++++++++++++++++++++++- Misc/NEWS | 6 +- Objects/stringlib/codecs.h | 92 ++++++--- Objects/unicodeobject.c | 10 +- 4 files changed, 292 insertions(+), 38 deletions(-) diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -1349,7 +1349,7 @@ # with start byte of a 2-byte sequence (b'\xc2', FFFD), # only the start byte (b'\xc2\xc2', FFFD*2), # 2 start bytes - (b'\xc2\xc2\xc2', FFFD*3), # 2 start bytes + (b'\xc2\xc2\xc2', FFFD*3), # 3 start bytes (b'\xc2\x41', FFFD+'A'), # invalid continuation byte # with start byte of a 3-byte sequence (b'\xe1', FFFD), # only the start byte @@ -1419,6 +1419,226 @@ self.assertEqual(seq.decode('utf-8', 'ignore'), res.replace('\uFFFD', '')) + def to_bytestring(self, seq): + return bytes(int(c, 16) for c in seq.split()) + + def assertCorrectUTF8Decoding(self, seq, res, err): + """ + Check that an invalid UTF-8 sequence raises an UnicodeDecodeError when + 'strict' is used, returns res when 'replace' is used, and that doesn't + return anything when 'ignore' is used. + """ + with self.assertRaises(UnicodeDecodeError) as cm: + seq.decode('utf-8') + exc = cm.exception + + self.assertIn(err, str(exc)) + self.assertEqual(seq.decode('utf-8', 'replace'), res) + self.assertEqual((b'aaaa' + seq + b'bbbb').decode('utf-8', 'replace'), + 'aaaa' + res + 'bbbb') + res = res.replace('\ufffd', '') + self.assertEqual(seq.decode('utf-8', 'ignore'), res) + self.assertEqual((b'aaaa' + seq + b'bbbb').decode('utf-8', 'ignore'), + 'aaaa' + res + 'bbbb') + + def test_invalid_start_byte(self): + """ + Test that an 'invalid start byte' error is raised when the first byte + is not in the ASCII range or is not a valid start byte of a 2-, 3-, or + 4-bytes sequence. The invalid start byte is replaced with a single + U+FFFD when errors='replace'. + E.g. <80> is a continuation byte and can appear only after a start byte. + """ + FFFD = '\ufffd' + for byte in b'\x80\xA0\x9F\xBF\xC0\xC1\xF5\xFF': + self.assertCorrectUTF8Decoding(bytes([byte]), '\ufffd', + 'invalid start byte') + + def test_unexpected_end_of_data(self): + """ + Test that an 'unexpected end of data' error is raised when the string + ends after a start byte of a 2-, 3-, or 4-bytes sequence without having + enough continuation bytes. The incomplete sequence is replaced with a + single U+FFFD when errors='replace'. + E.g. in the sequence , F3 is the start byte of a 4-bytes + sequence, but it's followed by only 2 valid continuation bytes and the + last continuation bytes is missing. + Note: the continuation bytes must be all valid, if one of them is + invalid another error will be raised. + """ + sequences = [ + 'C2', 'DF', + 'E0 A0', 'E0 BF', 'E1 80', 'E1 BF', 'EC 80', 'EC BF', + 'ED 80', 'ED 9F', 'EE 80', 'EE BF', 'EF 80', 'EF BF', + 'F0 90', 'F0 BF', 'F0 90 80', 'F0 90 BF', 'F0 BF 80', 'F0 BF BF', + 'F1 80', 'F1 BF', 'F1 80 80', 'F1 80 BF', 'F1 BF 80', 'F1 BF BF', + 'F3 80', 'F3 BF', 'F3 80 80', 'F3 80 BF', 'F3 BF 80', 'F3 BF BF', + 'F4 80', 'F4 8F', 'F4 80 80', 'F4 80 BF', 'F4 8F 80', 'F4 8F BF' + ] + FFFD = '\ufffd' + for seq in sequences: + self.assertCorrectUTF8Decoding(self.to_bytestring(seq), '\ufffd', + 'unexpected end of data') + + def test_invalid_cb_for_2bytes_seq(self): + """ + Test that an 'invalid continuation byte' error is raised when the + continuation byte of a 2-bytes sequence is invalid. The start byte + is replaced by a single U+FFFD and the second byte is handled + separately when errors='replace'. + E.g. in the sequence , C2 is the start byte of a 2-bytes + sequence, but 41 is not a valid continuation byte because it's the + ASCII letter 'A'. + """ + FFFD = '\ufffd' + FFFDx2 = FFFD * 2 + sequences = [ + ('C2 00', FFFD+'\x00'), ('C2 7F', FFFD+'\x7f'), + ('C2 C0', FFFDx2), ('C2 FF', FFFDx2), + ('DF 00', FFFD+'\x00'), ('DF 7F', FFFD+'\x7f'), + ('DF C0', FFFDx2), ('DF FF', FFFDx2), + ] + for seq, res in sequences: + self.assertCorrectUTF8Decoding(self.to_bytestring(seq), res, + 'invalid continuation byte') + + def test_invalid_cb_for_3bytes_seq(self): + """ + Test that an 'invalid continuation byte' error is raised when the + continuation byte(s) of a 3-bytes sequence are invalid. When + errors='replace', if the first continuation byte is valid, the first + two bytes (start byte + 1st cb) are replaced by a single U+FFFD and the + third byte is handled separately, otherwise only the start byte is + replaced with a U+FFFD and the other continuation bytes are handled + separately. + E.g. in the sequence , E1 is the start byte of a 3-bytes + sequence, 80 is a valid continuation byte, but 41 is not a valid cb + because it's the ASCII letter 'A'. + Note: when the start byte is E0 or ED, the valid ranges for the first + continuation byte are limited to A0..BF and 80..9F respectively. + Python 2 used to consider all the bytes in range 80..BF valid when the + start byte was ED. This is fixed in Python 3. + """ + FFFD = '\ufffd' + FFFDx2 = FFFD * 2 + sequences = [ + ('E0 00', FFFD+'\x00'), ('E0 7F', FFFD+'\x7f'), ('E0 80', FFFDx2), + ('E0 9F', FFFDx2), ('E0 C0', FFFDx2), ('E0 FF', FFFDx2), + ('E0 A0 00', FFFD+'\x00'), ('E0 A0 7F', FFFD+'\x7f'), + ('E0 A0 C0', FFFDx2), ('E0 A0 FF', FFFDx2), + ('E0 BF 00', FFFD+'\x00'), ('E0 BF 7F', FFFD+'\x7f'), + ('E0 BF C0', FFFDx2), ('E0 BF FF', FFFDx2), ('E1 00', FFFD+'\x00'), + ('E1 7F', FFFD+'\x7f'), ('E1 C0', FFFDx2), ('E1 FF', FFFDx2), + ('E1 80 00', FFFD+'\x00'), ('E1 80 7F', FFFD+'\x7f'), + ('E1 80 C0', FFFDx2), ('E1 80 FF', FFFDx2), + ('E1 BF 00', FFFD+'\x00'), ('E1 BF 7F', FFFD+'\x7f'), + ('E1 BF C0', FFFDx2), ('E1 BF FF', FFFDx2), ('EC 00', FFFD+'\x00'), + ('EC 7F', FFFD+'\x7f'), ('EC C0', FFFDx2), ('EC FF', FFFDx2), + ('EC 80 00', FFFD+'\x00'), ('EC 80 7F', FFFD+'\x7f'), + ('EC 80 C0', FFFDx2), ('EC 80 FF', FFFDx2), + ('EC BF 00', FFFD+'\x00'), ('EC BF 7F', FFFD+'\x7f'), + ('EC BF C0', FFFDx2), ('EC BF FF', FFFDx2), ('ED 00', FFFD+'\x00'), + ('ED 7F', FFFD+'\x7f'), + ('ED A0', FFFDx2), ('ED BF', FFFDx2), # see note ^ + ('ED C0', FFFDx2), ('ED FF', FFFDx2), ('ED 80 00', FFFD+'\x00'), + ('ED 80 7F', FFFD+'\x7f'), ('ED 80 C0', FFFDx2), + ('ED 80 FF', FFFDx2), ('ED 9F 00', FFFD+'\x00'), + ('ED 9F 7F', FFFD+'\x7f'), ('ED 9F C0', FFFDx2), + ('ED 9F FF', FFFDx2), ('EE 00', FFFD+'\x00'), + ('EE 7F', FFFD+'\x7f'), ('EE C0', FFFDx2), ('EE FF', FFFDx2), + ('EE 80 00', FFFD+'\x00'), ('EE 80 7F', FFFD+'\x7f'), + ('EE 80 C0', FFFDx2), ('EE 80 FF', FFFDx2), + ('EE BF 00', FFFD+'\x00'), ('EE BF 7F', FFFD+'\x7f'), + ('EE BF C0', FFFDx2), ('EE BF FF', FFFDx2), ('EF 00', FFFD+'\x00'), + ('EF 7F', FFFD+'\x7f'), ('EF C0', FFFDx2), ('EF FF', FFFDx2), + ('EF 80 00', FFFD+'\x00'), ('EF 80 7F', FFFD+'\x7f'), + ('EF 80 C0', FFFDx2), ('EF 80 FF', FFFDx2), + ('EF BF 00', FFFD+'\x00'), ('EF BF 7F', FFFD+'\x7f'), + ('EF BF C0', FFFDx2), ('EF BF FF', FFFDx2), + ] + for seq, res in sequences: + self.assertCorrectUTF8Decoding(self.to_bytestring(seq), res, + 'invalid continuation byte') + + def test_invalid_cb_for_4bytes_seq(self): + """ + Test that an 'invalid continuation byte' error is raised when the + continuation byte(s) of a 4-bytes sequence are invalid. When + errors='replace',the start byte and all the following valid + continuation bytes are replaced with a single U+FFFD, and all the bytes + starting from the first invalid continuation bytes (included) are + handled separately. + E.g. in the sequence , E1 is the start byte of a 3-bytes + sequence, 80 is a valid continuation byte, but 41 is not a valid cb + because it's the ASCII letter 'A'. + Note: when the start byte is E0 or ED, the valid ranges for the first + continuation byte are limited to A0..BF and 80..9F respectively. + However, when the start byte is ED, Python 2 considers all the bytes + in range 80..BF valid. This is fixed in Python 3. + """ + FFFD = '\ufffd' + FFFDx2 = FFFD * 2 + sequences = [ + ('F0 00', FFFD+'\x00'), ('F0 7F', FFFD+'\x7f'), ('F0 80', FFFDx2), + ('F0 8F', FFFDx2), ('F0 C0', FFFDx2), ('F0 FF', FFFDx2), + ('F0 90 00', FFFD+'\x00'), ('F0 90 7F', FFFD+'\x7f'), + ('F0 90 C0', FFFDx2), ('F0 90 FF', FFFDx2), + ('F0 BF 00', FFFD+'\x00'), ('F0 BF 7F', FFFD+'\x7f'), + ('F0 BF C0', FFFDx2), ('F0 BF FF', FFFDx2), + ('F0 90 80 00', FFFD+'\x00'), ('F0 90 80 7F', FFFD+'\x7f'), + ('F0 90 80 C0', FFFDx2), ('F0 90 80 FF', FFFDx2), + ('F0 90 BF 00', FFFD+'\x00'), ('F0 90 BF 7F', FFFD+'\x7f'), + ('F0 90 BF C0', FFFDx2), ('F0 90 BF FF', FFFDx2), + ('F0 BF 80 00', FFFD+'\x00'), ('F0 BF 80 7F', FFFD+'\x7f'), + ('F0 BF 80 C0', FFFDx2), ('F0 BF 80 FF', FFFDx2), + ('F0 BF BF 00', FFFD+'\x00'), ('F0 BF BF 7F', FFFD+'\x7f'), + ('F0 BF BF C0', FFFDx2), ('F0 BF BF FF', FFFDx2), + ('F1 00', FFFD+'\x00'), ('F1 7F', FFFD+'\x7f'), ('F1 C0', FFFDx2), + ('F1 FF', FFFDx2), ('F1 80 00', FFFD+'\x00'), + ('F1 80 7F', FFFD+'\x7f'), ('F1 80 C0', FFFDx2), + ('F1 80 FF', FFFDx2), ('F1 BF 00', FFFD+'\x00'), + ('F1 BF 7F', FFFD+'\x7f'), ('F1 BF C0', FFFDx2), + ('F1 BF FF', FFFDx2), ('F1 80 80 00', FFFD+'\x00'), + ('F1 80 80 7F', FFFD+'\x7f'), ('F1 80 80 C0', FFFDx2), + ('F1 80 80 FF', FFFDx2), ('F1 80 BF 00', FFFD+'\x00'), + ('F1 80 BF 7F', FFFD+'\x7f'), ('F1 80 BF C0', FFFDx2), + ('F1 80 BF FF', FFFDx2), ('F1 BF 80 00', FFFD+'\x00'), + ('F1 BF 80 7F', FFFD+'\x7f'), ('F1 BF 80 C0', FFFDx2), + ('F1 BF 80 FF', FFFDx2), ('F1 BF BF 00', FFFD+'\x00'), + ('F1 BF BF 7F', FFFD+'\x7f'), ('F1 BF BF C0', FFFDx2), + ('F1 BF BF FF', FFFDx2), ('F3 00', FFFD+'\x00'), + ('F3 7F', FFFD+'\x7f'), ('F3 C0', FFFDx2), ('F3 FF', FFFDx2), + ('F3 80 00', FFFD+'\x00'), ('F3 80 7F', FFFD+'\x7f'), + ('F3 80 C0', FFFDx2), ('F3 80 FF', FFFDx2), + ('F3 BF 00', FFFD+'\x00'), ('F3 BF 7F', FFFD+'\x7f'), + ('F3 BF C0', FFFDx2), ('F3 BF FF', FFFDx2), + ('F3 80 80 00', FFFD+'\x00'), ('F3 80 80 7F', FFFD+'\x7f'), + ('F3 80 80 C0', FFFDx2), ('F3 80 80 FF', FFFDx2), + ('F3 80 BF 00', FFFD+'\x00'), ('F3 80 BF 7F', FFFD+'\x7f'), + ('F3 80 BF C0', FFFDx2), ('F3 80 BF FF', FFFDx2), + ('F3 BF 80 00', FFFD+'\x00'), ('F3 BF 80 7F', FFFD+'\x7f'), + ('F3 BF 80 C0', FFFDx2), ('F3 BF 80 FF', FFFDx2), + ('F3 BF BF 00', FFFD+'\x00'), ('F3 BF BF 7F', FFFD+'\x7f'), + ('F3 BF BF C0', FFFDx2), ('F3 BF BF FF', FFFDx2), + ('F4 00', FFFD+'\x00'), ('F4 7F', FFFD+'\x7f'), ('F4 90', FFFDx2), + ('F4 BF', FFFDx2), ('F4 C0', FFFDx2), ('F4 FF', FFFDx2), + ('F4 80 00', FFFD+'\x00'), ('F4 80 7F', FFFD+'\x7f'), + ('F4 80 C0', FFFDx2), ('F4 80 FF', FFFDx2), + ('F4 8F 00', FFFD+'\x00'), ('F4 8F 7F', FFFD+'\x7f'), + ('F4 8F C0', FFFDx2), ('F4 8F FF', FFFDx2), + ('F4 80 80 00', FFFD+'\x00'), ('F4 80 80 7F', FFFD+'\x7f'), + ('F4 80 80 C0', FFFDx2), ('F4 80 80 FF', FFFDx2), + ('F4 80 BF 00', FFFD+'\x00'), ('F4 80 BF 7F', FFFD+'\x7f'), + ('F4 80 BF C0', FFFDx2), ('F4 80 BF FF', FFFDx2), + ('F4 8F 80 00', FFFD+'\x00'), ('F4 8F 80 7F', FFFD+'\x7f'), + ('F4 8F 80 C0', FFFDx2), ('F4 8F 80 FF', FFFDx2), + ('F4 8F BF 00', FFFD+'\x00'), ('F4 8F BF 7F', FFFD+'\x7f'), + ('F4 8F BF C0', FFFDx2), ('F4 8F BF FF', FFFDx2) + ] + for seq, res in sequences: + self.assertCorrectUTF8Decoding(self.to_bytestring(seq), res, + 'invalid continuation byte') + def test_codecs_idna(self): # Test whether trailing dot is preserved self.assertEqual("www.python.org.".encode("idna"), b"www.python.org.") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,10 @@ Core and Builtins ----------------- +- Issue #8271: the utf-8 decoder now outputs the correct number of U+FFFD + characters when used with the 'replace' error handler on invalid utf-8 + sequences. Patch by Serhiy Storchaka, tests by Ezio Melotti. + - Issue #5765: Apply a hard recursion limit in the compiler instead of blowing the stack and segfaulting. Initial patch by Andrea Griffini. @@ -33,7 +37,7 @@ - Issue #16271: Fix strange bugs that resulted from __qualname__ appearing in a class's __dict__ and on type. -- Issue #16197: Update winreg docstrings and documentation to match code. +- Issue #16197: Update winreg docstrings and documentation to match code. Patch by Zachary Ware. - Issue #16241: Document -X faulthandler command line option. diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -91,15 +91,14 @@ } } - if (ch < 0xC2) { - /* invalid sequence - \x80-\xBF -- continuation byte - \xC0-\xC1 -- fake 0000-007F */ - goto InvalidStart; - } - if (ch < 0xE0) { /* \xC2\x80-\xDF\xBF -- 0080-07FF */ + if (ch < 0xC2) { + /* invalid sequence + \x80-\xBF -- continuation byte + \xC0-\xC1 -- fake 0000-007F */ + goto InvalidStart; + } Py_UCS4 ch2; if (end - s < 2) { /* unexpected end of data: the caller will decide whether @@ -109,14 +108,15 @@ ch2 = (unsigned char)s[1]; if (!IS_CONTINUATION_BYTE(ch2)) /* invalid continuation byte */ - goto InvalidContinuation; + goto InvalidContinuation1; ch = (ch << 6) + ch2 - ((0xC0 << 6) + 0x80); assert ((ch > 0x007F) && (ch <= 0x07FF)); s += 2; if (STRINGLIB_MAX_CHAR <= 0x007F || (STRINGLIB_MAX_CHAR < 0x07FF && ch > STRINGLIB_MAX_CHAR)) - goto Overflow; + /* Out-of-range */ + goto Return; *p++ = ch; continue; } @@ -127,28 +127,37 @@ if (end - s < 3) { /* unexpected end of data: the caller will decide whether it's an error or not */ + if (end - s < 2) + break; + ch2 = (unsigned char)s[1]; + if (!IS_CONTINUATION_BYTE(ch2) || + (ch2 < 0xA0 ? ch == 0xE0 : ch == 0xED)) + /* for clarification see comments below */ + goto InvalidContinuation1; break; } ch2 = (unsigned char)s[1]; ch3 = (unsigned char)s[2]; - if (!IS_CONTINUATION_BYTE(ch2) || - !IS_CONTINUATION_BYTE(ch3)) { + if (!IS_CONTINUATION_BYTE(ch2)) { /* invalid continuation byte */ - goto InvalidContinuation; + goto InvalidContinuation1; } if (ch == 0xE0) { if (ch2 < 0xA0) /* invalid sequence \xE0\x80\x80-\xE0\x9F\xBF -- fake 0000-0800 */ - goto InvalidContinuation; - } - else if (ch == 0xED && ch2 > 0x9F) { + goto InvalidContinuation1; + } else if (ch == 0xED && ch2 >= 0xA0) { /* Decoding UTF-8 sequences in range \xED\xA0\x80-\xED\xBF\xBF will result in surrogates in range D800-DFFF. Surrogates are not valid UTF-8 so they are rejected. See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf (table 3-7) and http://www.rfc-editor.org/rfc/rfc3629.txt */ - goto InvalidContinuation; + goto InvalidContinuation1; + } + if (!IS_CONTINUATION_BYTE(ch3)) { + /* invalid continuation byte */ + goto InvalidContinuation2; } ch = (ch << 12) + (ch2 << 6) + ch3 - ((0xE0 << 12) + (0x80 << 6) + 0x80); @@ -156,7 +165,8 @@ s += 3; if (STRINGLIB_MAX_CHAR <= 0x07FF || (STRINGLIB_MAX_CHAR < 0xFFFF && ch > STRINGLIB_MAX_CHAR)) - goto Overflow; + /* Out-of-range */ + goto Return; *p++ = ch; continue; } @@ -167,27 +177,44 @@ if (end - s < 4) { /* unexpected end of data: the caller will decide whether it's an error or not */ + if (end - s < 2) + break; + ch2 = (unsigned char)s[1]; + if (!IS_CONTINUATION_BYTE(ch2) || + (ch2 < 0x90 ? ch == 0xF0 : ch == 0xF4)) + /* for clarification see comments below */ + goto InvalidContinuation1; + if (end - s < 3) + break; + ch3 = (unsigned char)s[2]; + if (!IS_CONTINUATION_BYTE(ch3)) + goto InvalidContinuation2; break; } ch2 = (unsigned char)s[1]; ch3 = (unsigned char)s[2]; ch4 = (unsigned char)s[3]; - if (!IS_CONTINUATION_BYTE(ch2) || - !IS_CONTINUATION_BYTE(ch3) || - !IS_CONTINUATION_BYTE(ch4)) { + if (!IS_CONTINUATION_BYTE(ch2)) { /* invalid continuation byte */ - goto InvalidContinuation; + goto InvalidContinuation1; } if (ch == 0xF0) { if (ch2 < 0x90) /* invalid sequence - \xF0\x80\x80\x80-\xF0\x80\xBF\xBF -- fake 0000-FFFF */ - goto InvalidContinuation; - } - else if (ch == 0xF4 && ch2 > 0x8F) { + \xF0\x80\x80\x80-\xF0\x8F\xBF\xBF -- fake 0000-FFFF */ + goto InvalidContinuation1; + } else if (ch == 0xF4 && ch2 >= 0x90) { /* invalid sequence \xF4\x90\x80\80- -- 110000- overflow */ - goto InvalidContinuation; + goto InvalidContinuation1; + } + if (!IS_CONTINUATION_BYTE(ch3)) { + /* invalid continuation byte */ + goto InvalidContinuation2; + } + if (!IS_CONTINUATION_BYTE(ch4)) { + /* invalid continuation byte */ + goto InvalidContinuation3; } ch = (ch << 18) + (ch2 << 12) + (ch3 << 6) + ch4 - ((0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80); @@ -195,14 +222,14 @@ s += 4; if (STRINGLIB_MAX_CHAR <= 0xFFFF || (STRINGLIB_MAX_CHAR < 0x10FFFF && ch > STRINGLIB_MAX_CHAR)) - goto Overflow; + /* Out-of-range */ + goto Return; *p++ = ch; continue; } goto InvalidStart; } ch = 0; -Overflow: Return: *inptr = s; *outpos = p - dest; @@ -210,13 +237,18 @@ InvalidStart: ch = 1; goto Return; -InvalidContinuation: +InvalidContinuation1: ch = 2; goto Return; +InvalidContinuation2: + ch = 3; + goto Return; +InvalidContinuation3: + ch = 4; + goto Return; } #undef ASCII_CHAR_MASK -#undef IS_CONTINUATION_BYTE /* UTF-8 encoder specialized for a Unicode kind to avoid the slow diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -4759,9 +4759,7 @@ goto End; errmsg = "unexpected end of data"; startinpos = s - starts; - endinpos = startinpos + 1; - while (endinpos < size && (starts[endinpos] & 0xC0) == 0x80) - endinpos++; + endinpos = end - starts; break; case 1: errmsg = "invalid start byte"; @@ -4769,11 +4767,11 @@ endinpos = startinpos + 1; break; case 2: + case 3: + case 4: errmsg = "invalid continuation byte"; startinpos = s - starts; - endinpos = startinpos + 1; - while (endinpos < size && (starts[endinpos] & 0xC0) == 0x80) - endinpos++; + endinpos = startinpos + ch - 1; break; default: if (unicode_putchar(&unicode, &outpos, ch) < 0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 22:23:39 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 22:23:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzgyNzE6IG1lcmdlIHdpdGggMy4zLg==?= Message-ID: <3Xvqkz2B4GzRKd@mail.python.org> http://hg.python.org/cpython/rev/5b205fff1972 changeset: 80247:5b205fff1972 parent: 80245:fc8f1b1c76bf parent: 80246:5962f192a483 user: Ezio Melotti date: Sun Nov 04 23:23:09 2012 +0200 summary: #8271: merge with 3.3. files: Lib/test/test_unicode.py | 222 ++++++++++++++++++++++++- Misc/NEWS | 4 + Objects/stringlib/codecs.h | 92 ++++++--- Objects/unicodeobject.c | 10 +- 4 files changed, 291 insertions(+), 37 deletions(-) diff --git a/Lib/test/test_unicode.py b/Lib/test/test_unicode.py --- a/Lib/test/test_unicode.py +++ b/Lib/test/test_unicode.py @@ -1349,7 +1349,7 @@ # with start byte of a 2-byte sequence (b'\xc2', FFFD), # only the start byte (b'\xc2\xc2', FFFD*2), # 2 start bytes - (b'\xc2\xc2\xc2', FFFD*3), # 2 start bytes + (b'\xc2\xc2\xc2', FFFD*3), # 3 start bytes (b'\xc2\x41', FFFD+'A'), # invalid continuation byte # with start byte of a 3-byte sequence (b'\xe1', FFFD), # only the start byte @@ -1419,6 +1419,226 @@ self.assertEqual(seq.decode('utf-8', 'ignore'), res.replace('\uFFFD', '')) + def to_bytestring(self, seq): + return bytes(int(c, 16) for c in seq.split()) + + def assertCorrectUTF8Decoding(self, seq, res, err): + """ + Check that an invalid UTF-8 sequence raises an UnicodeDecodeError when + 'strict' is used, returns res when 'replace' is used, and that doesn't + return anything when 'ignore' is used. + """ + with self.assertRaises(UnicodeDecodeError) as cm: + seq.decode('utf-8') + exc = cm.exception + + self.assertIn(err, str(exc)) + self.assertEqual(seq.decode('utf-8', 'replace'), res) + self.assertEqual((b'aaaa' + seq + b'bbbb').decode('utf-8', 'replace'), + 'aaaa' + res + 'bbbb') + res = res.replace('\ufffd', '') + self.assertEqual(seq.decode('utf-8', 'ignore'), res) + self.assertEqual((b'aaaa' + seq + b'bbbb').decode('utf-8', 'ignore'), + 'aaaa' + res + 'bbbb') + + def test_invalid_start_byte(self): + """ + Test that an 'invalid start byte' error is raised when the first byte + is not in the ASCII range or is not a valid start byte of a 2-, 3-, or + 4-bytes sequence. The invalid start byte is replaced with a single + U+FFFD when errors='replace'. + E.g. <80> is a continuation byte and can appear only after a start byte. + """ + FFFD = '\ufffd' + for byte in b'\x80\xA0\x9F\xBF\xC0\xC1\xF5\xFF': + self.assertCorrectUTF8Decoding(bytes([byte]), '\ufffd', + 'invalid start byte') + + def test_unexpected_end_of_data(self): + """ + Test that an 'unexpected end of data' error is raised when the string + ends after a start byte of a 2-, 3-, or 4-bytes sequence without having + enough continuation bytes. The incomplete sequence is replaced with a + single U+FFFD when errors='replace'. + E.g. in the sequence , F3 is the start byte of a 4-bytes + sequence, but it's followed by only 2 valid continuation bytes and the + last continuation bytes is missing. + Note: the continuation bytes must be all valid, if one of them is + invalid another error will be raised. + """ + sequences = [ + 'C2', 'DF', + 'E0 A0', 'E0 BF', 'E1 80', 'E1 BF', 'EC 80', 'EC BF', + 'ED 80', 'ED 9F', 'EE 80', 'EE BF', 'EF 80', 'EF BF', + 'F0 90', 'F0 BF', 'F0 90 80', 'F0 90 BF', 'F0 BF 80', 'F0 BF BF', + 'F1 80', 'F1 BF', 'F1 80 80', 'F1 80 BF', 'F1 BF 80', 'F1 BF BF', + 'F3 80', 'F3 BF', 'F3 80 80', 'F3 80 BF', 'F3 BF 80', 'F3 BF BF', + 'F4 80', 'F4 8F', 'F4 80 80', 'F4 80 BF', 'F4 8F 80', 'F4 8F BF' + ] + FFFD = '\ufffd' + for seq in sequences: + self.assertCorrectUTF8Decoding(self.to_bytestring(seq), '\ufffd', + 'unexpected end of data') + + def test_invalid_cb_for_2bytes_seq(self): + """ + Test that an 'invalid continuation byte' error is raised when the + continuation byte of a 2-bytes sequence is invalid. The start byte + is replaced by a single U+FFFD and the second byte is handled + separately when errors='replace'. + E.g. in the sequence , C2 is the start byte of a 2-bytes + sequence, but 41 is not a valid continuation byte because it's the + ASCII letter 'A'. + """ + FFFD = '\ufffd' + FFFDx2 = FFFD * 2 + sequences = [ + ('C2 00', FFFD+'\x00'), ('C2 7F', FFFD+'\x7f'), + ('C2 C0', FFFDx2), ('C2 FF', FFFDx2), + ('DF 00', FFFD+'\x00'), ('DF 7F', FFFD+'\x7f'), + ('DF C0', FFFDx2), ('DF FF', FFFDx2), + ] + for seq, res in sequences: + self.assertCorrectUTF8Decoding(self.to_bytestring(seq), res, + 'invalid continuation byte') + + def test_invalid_cb_for_3bytes_seq(self): + """ + Test that an 'invalid continuation byte' error is raised when the + continuation byte(s) of a 3-bytes sequence are invalid. When + errors='replace', if the first continuation byte is valid, the first + two bytes (start byte + 1st cb) are replaced by a single U+FFFD and the + third byte is handled separately, otherwise only the start byte is + replaced with a U+FFFD and the other continuation bytes are handled + separately. + E.g. in the sequence , E1 is the start byte of a 3-bytes + sequence, 80 is a valid continuation byte, but 41 is not a valid cb + because it's the ASCII letter 'A'. + Note: when the start byte is E0 or ED, the valid ranges for the first + continuation byte are limited to A0..BF and 80..9F respectively. + Python 2 used to consider all the bytes in range 80..BF valid when the + start byte was ED. This is fixed in Python 3. + """ + FFFD = '\ufffd' + FFFDx2 = FFFD * 2 + sequences = [ + ('E0 00', FFFD+'\x00'), ('E0 7F', FFFD+'\x7f'), ('E0 80', FFFDx2), + ('E0 9F', FFFDx2), ('E0 C0', FFFDx2), ('E0 FF', FFFDx2), + ('E0 A0 00', FFFD+'\x00'), ('E0 A0 7F', FFFD+'\x7f'), + ('E0 A0 C0', FFFDx2), ('E0 A0 FF', FFFDx2), + ('E0 BF 00', FFFD+'\x00'), ('E0 BF 7F', FFFD+'\x7f'), + ('E0 BF C0', FFFDx2), ('E0 BF FF', FFFDx2), ('E1 00', FFFD+'\x00'), + ('E1 7F', FFFD+'\x7f'), ('E1 C0', FFFDx2), ('E1 FF', FFFDx2), + ('E1 80 00', FFFD+'\x00'), ('E1 80 7F', FFFD+'\x7f'), + ('E1 80 C0', FFFDx2), ('E1 80 FF', FFFDx2), + ('E1 BF 00', FFFD+'\x00'), ('E1 BF 7F', FFFD+'\x7f'), + ('E1 BF C0', FFFDx2), ('E1 BF FF', FFFDx2), ('EC 00', FFFD+'\x00'), + ('EC 7F', FFFD+'\x7f'), ('EC C0', FFFDx2), ('EC FF', FFFDx2), + ('EC 80 00', FFFD+'\x00'), ('EC 80 7F', FFFD+'\x7f'), + ('EC 80 C0', FFFDx2), ('EC 80 FF', FFFDx2), + ('EC BF 00', FFFD+'\x00'), ('EC BF 7F', FFFD+'\x7f'), + ('EC BF C0', FFFDx2), ('EC BF FF', FFFDx2), ('ED 00', FFFD+'\x00'), + ('ED 7F', FFFD+'\x7f'), + ('ED A0', FFFDx2), ('ED BF', FFFDx2), # see note ^ + ('ED C0', FFFDx2), ('ED FF', FFFDx2), ('ED 80 00', FFFD+'\x00'), + ('ED 80 7F', FFFD+'\x7f'), ('ED 80 C0', FFFDx2), + ('ED 80 FF', FFFDx2), ('ED 9F 00', FFFD+'\x00'), + ('ED 9F 7F', FFFD+'\x7f'), ('ED 9F C0', FFFDx2), + ('ED 9F FF', FFFDx2), ('EE 00', FFFD+'\x00'), + ('EE 7F', FFFD+'\x7f'), ('EE C0', FFFDx2), ('EE FF', FFFDx2), + ('EE 80 00', FFFD+'\x00'), ('EE 80 7F', FFFD+'\x7f'), + ('EE 80 C0', FFFDx2), ('EE 80 FF', FFFDx2), + ('EE BF 00', FFFD+'\x00'), ('EE BF 7F', FFFD+'\x7f'), + ('EE BF C0', FFFDx2), ('EE BF FF', FFFDx2), ('EF 00', FFFD+'\x00'), + ('EF 7F', FFFD+'\x7f'), ('EF C0', FFFDx2), ('EF FF', FFFDx2), + ('EF 80 00', FFFD+'\x00'), ('EF 80 7F', FFFD+'\x7f'), + ('EF 80 C0', FFFDx2), ('EF 80 FF', FFFDx2), + ('EF BF 00', FFFD+'\x00'), ('EF BF 7F', FFFD+'\x7f'), + ('EF BF C0', FFFDx2), ('EF BF FF', FFFDx2), + ] + for seq, res in sequences: + self.assertCorrectUTF8Decoding(self.to_bytestring(seq), res, + 'invalid continuation byte') + + def test_invalid_cb_for_4bytes_seq(self): + """ + Test that an 'invalid continuation byte' error is raised when the + continuation byte(s) of a 4-bytes sequence are invalid. When + errors='replace',the start byte and all the following valid + continuation bytes are replaced with a single U+FFFD, and all the bytes + starting from the first invalid continuation bytes (included) are + handled separately. + E.g. in the sequence , E1 is the start byte of a 3-bytes + sequence, 80 is a valid continuation byte, but 41 is not a valid cb + because it's the ASCII letter 'A'. + Note: when the start byte is E0 or ED, the valid ranges for the first + continuation byte are limited to A0..BF and 80..9F respectively. + However, when the start byte is ED, Python 2 considers all the bytes + in range 80..BF valid. This is fixed in Python 3. + """ + FFFD = '\ufffd' + FFFDx2 = FFFD * 2 + sequences = [ + ('F0 00', FFFD+'\x00'), ('F0 7F', FFFD+'\x7f'), ('F0 80', FFFDx2), + ('F0 8F', FFFDx2), ('F0 C0', FFFDx2), ('F0 FF', FFFDx2), + ('F0 90 00', FFFD+'\x00'), ('F0 90 7F', FFFD+'\x7f'), + ('F0 90 C0', FFFDx2), ('F0 90 FF', FFFDx2), + ('F0 BF 00', FFFD+'\x00'), ('F0 BF 7F', FFFD+'\x7f'), + ('F0 BF C0', FFFDx2), ('F0 BF FF', FFFDx2), + ('F0 90 80 00', FFFD+'\x00'), ('F0 90 80 7F', FFFD+'\x7f'), + ('F0 90 80 C0', FFFDx2), ('F0 90 80 FF', FFFDx2), + ('F0 90 BF 00', FFFD+'\x00'), ('F0 90 BF 7F', FFFD+'\x7f'), + ('F0 90 BF C0', FFFDx2), ('F0 90 BF FF', FFFDx2), + ('F0 BF 80 00', FFFD+'\x00'), ('F0 BF 80 7F', FFFD+'\x7f'), + ('F0 BF 80 C0', FFFDx2), ('F0 BF 80 FF', FFFDx2), + ('F0 BF BF 00', FFFD+'\x00'), ('F0 BF BF 7F', FFFD+'\x7f'), + ('F0 BF BF C0', FFFDx2), ('F0 BF BF FF', FFFDx2), + ('F1 00', FFFD+'\x00'), ('F1 7F', FFFD+'\x7f'), ('F1 C0', FFFDx2), + ('F1 FF', FFFDx2), ('F1 80 00', FFFD+'\x00'), + ('F1 80 7F', FFFD+'\x7f'), ('F1 80 C0', FFFDx2), + ('F1 80 FF', FFFDx2), ('F1 BF 00', FFFD+'\x00'), + ('F1 BF 7F', FFFD+'\x7f'), ('F1 BF C0', FFFDx2), + ('F1 BF FF', FFFDx2), ('F1 80 80 00', FFFD+'\x00'), + ('F1 80 80 7F', FFFD+'\x7f'), ('F1 80 80 C0', FFFDx2), + ('F1 80 80 FF', FFFDx2), ('F1 80 BF 00', FFFD+'\x00'), + ('F1 80 BF 7F', FFFD+'\x7f'), ('F1 80 BF C0', FFFDx2), + ('F1 80 BF FF', FFFDx2), ('F1 BF 80 00', FFFD+'\x00'), + ('F1 BF 80 7F', FFFD+'\x7f'), ('F1 BF 80 C0', FFFDx2), + ('F1 BF 80 FF', FFFDx2), ('F1 BF BF 00', FFFD+'\x00'), + ('F1 BF BF 7F', FFFD+'\x7f'), ('F1 BF BF C0', FFFDx2), + ('F1 BF BF FF', FFFDx2), ('F3 00', FFFD+'\x00'), + ('F3 7F', FFFD+'\x7f'), ('F3 C0', FFFDx2), ('F3 FF', FFFDx2), + ('F3 80 00', FFFD+'\x00'), ('F3 80 7F', FFFD+'\x7f'), + ('F3 80 C0', FFFDx2), ('F3 80 FF', FFFDx2), + ('F3 BF 00', FFFD+'\x00'), ('F3 BF 7F', FFFD+'\x7f'), + ('F3 BF C0', FFFDx2), ('F3 BF FF', FFFDx2), + ('F3 80 80 00', FFFD+'\x00'), ('F3 80 80 7F', FFFD+'\x7f'), + ('F3 80 80 C0', FFFDx2), ('F3 80 80 FF', FFFDx2), + ('F3 80 BF 00', FFFD+'\x00'), ('F3 80 BF 7F', FFFD+'\x7f'), + ('F3 80 BF C0', FFFDx2), ('F3 80 BF FF', FFFDx2), + ('F3 BF 80 00', FFFD+'\x00'), ('F3 BF 80 7F', FFFD+'\x7f'), + ('F3 BF 80 C0', FFFDx2), ('F3 BF 80 FF', FFFDx2), + ('F3 BF BF 00', FFFD+'\x00'), ('F3 BF BF 7F', FFFD+'\x7f'), + ('F3 BF BF C0', FFFDx2), ('F3 BF BF FF', FFFDx2), + ('F4 00', FFFD+'\x00'), ('F4 7F', FFFD+'\x7f'), ('F4 90', FFFDx2), + ('F4 BF', FFFDx2), ('F4 C0', FFFDx2), ('F4 FF', FFFDx2), + ('F4 80 00', FFFD+'\x00'), ('F4 80 7F', FFFD+'\x7f'), + ('F4 80 C0', FFFDx2), ('F4 80 FF', FFFDx2), + ('F4 8F 00', FFFD+'\x00'), ('F4 8F 7F', FFFD+'\x7f'), + ('F4 8F C0', FFFDx2), ('F4 8F FF', FFFDx2), + ('F4 80 80 00', FFFD+'\x00'), ('F4 80 80 7F', FFFD+'\x7f'), + ('F4 80 80 C0', FFFDx2), ('F4 80 80 FF', FFFDx2), + ('F4 80 BF 00', FFFD+'\x00'), ('F4 80 BF 7F', FFFD+'\x7f'), + ('F4 80 BF C0', FFFDx2), ('F4 80 BF FF', FFFDx2), + ('F4 8F 80 00', FFFD+'\x00'), ('F4 8F 80 7F', FFFD+'\x7f'), + ('F4 8F 80 C0', FFFDx2), ('F4 8F 80 FF', FFFDx2), + ('F4 8F BF 00', FFFD+'\x00'), ('F4 8F BF 7F', FFFD+'\x7f'), + ('F4 8F BF C0', FFFDx2), ('F4 8F BF FF', FFFDx2) + ] + for seq, res in sequences: + self.assertCorrectUTF8Decoding(self.to_bytestring(seq), res, + 'invalid continuation byte') + def test_codecs_idna(self): # Test whether trailing dot is preserved self.assertEqual("www.python.org.".encode("idna"), b"www.python.org.") diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #8271: the utf-8 decoder now outputs the correct number of U+FFFD + characters when used with the 'replace' error handler on invalid utf-8 + sequences. Patch by Serhiy Storchaka, tests by Ezio Melotti. + - Issue #5765: Apply a hard recursion limit in the compiler instead of blowing the stack and segfaulting. Initial patch by Andrea Griffini. diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -91,15 +91,14 @@ } } - if (ch < 0xC2) { - /* invalid sequence - \x80-\xBF -- continuation byte - \xC0-\xC1 -- fake 0000-007F */ - goto InvalidStart; - } - if (ch < 0xE0) { /* \xC2\x80-\xDF\xBF -- 0080-07FF */ + if (ch < 0xC2) { + /* invalid sequence + \x80-\xBF -- continuation byte + \xC0-\xC1 -- fake 0000-007F */ + goto InvalidStart; + } Py_UCS4 ch2; if (end - s < 2) { /* unexpected end of data: the caller will decide whether @@ -109,14 +108,15 @@ ch2 = (unsigned char)s[1]; if (!IS_CONTINUATION_BYTE(ch2)) /* invalid continuation byte */ - goto InvalidContinuation; + goto InvalidContinuation1; ch = (ch << 6) + ch2 - ((0xC0 << 6) + 0x80); assert ((ch > 0x007F) && (ch <= 0x07FF)); s += 2; if (STRINGLIB_MAX_CHAR <= 0x007F || (STRINGLIB_MAX_CHAR < 0x07FF && ch > STRINGLIB_MAX_CHAR)) - goto Overflow; + /* Out-of-range */ + goto Return; *p++ = ch; continue; } @@ -127,28 +127,37 @@ if (end - s < 3) { /* unexpected end of data: the caller will decide whether it's an error or not */ + if (end - s < 2) + break; + ch2 = (unsigned char)s[1]; + if (!IS_CONTINUATION_BYTE(ch2) || + (ch2 < 0xA0 ? ch == 0xE0 : ch == 0xED)) + /* for clarification see comments below */ + goto InvalidContinuation1; break; } ch2 = (unsigned char)s[1]; ch3 = (unsigned char)s[2]; - if (!IS_CONTINUATION_BYTE(ch2) || - !IS_CONTINUATION_BYTE(ch3)) { + if (!IS_CONTINUATION_BYTE(ch2)) { /* invalid continuation byte */ - goto InvalidContinuation; + goto InvalidContinuation1; } if (ch == 0xE0) { if (ch2 < 0xA0) /* invalid sequence \xE0\x80\x80-\xE0\x9F\xBF -- fake 0000-0800 */ - goto InvalidContinuation; - } - else if (ch == 0xED && ch2 > 0x9F) { + goto InvalidContinuation1; + } else if (ch == 0xED && ch2 >= 0xA0) { /* Decoding UTF-8 sequences in range \xED\xA0\x80-\xED\xBF\xBF will result in surrogates in range D800-DFFF. Surrogates are not valid UTF-8 so they are rejected. See http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf (table 3-7) and http://www.rfc-editor.org/rfc/rfc3629.txt */ - goto InvalidContinuation; + goto InvalidContinuation1; + } + if (!IS_CONTINUATION_BYTE(ch3)) { + /* invalid continuation byte */ + goto InvalidContinuation2; } ch = (ch << 12) + (ch2 << 6) + ch3 - ((0xE0 << 12) + (0x80 << 6) + 0x80); @@ -156,7 +165,8 @@ s += 3; if (STRINGLIB_MAX_CHAR <= 0x07FF || (STRINGLIB_MAX_CHAR < 0xFFFF && ch > STRINGLIB_MAX_CHAR)) - goto Overflow; + /* Out-of-range */ + goto Return; *p++ = ch; continue; } @@ -167,27 +177,44 @@ if (end - s < 4) { /* unexpected end of data: the caller will decide whether it's an error or not */ + if (end - s < 2) + break; + ch2 = (unsigned char)s[1]; + if (!IS_CONTINUATION_BYTE(ch2) || + (ch2 < 0x90 ? ch == 0xF0 : ch == 0xF4)) + /* for clarification see comments below */ + goto InvalidContinuation1; + if (end - s < 3) + break; + ch3 = (unsigned char)s[2]; + if (!IS_CONTINUATION_BYTE(ch3)) + goto InvalidContinuation2; break; } ch2 = (unsigned char)s[1]; ch3 = (unsigned char)s[2]; ch4 = (unsigned char)s[3]; - if (!IS_CONTINUATION_BYTE(ch2) || - !IS_CONTINUATION_BYTE(ch3) || - !IS_CONTINUATION_BYTE(ch4)) { + if (!IS_CONTINUATION_BYTE(ch2)) { /* invalid continuation byte */ - goto InvalidContinuation; + goto InvalidContinuation1; } if (ch == 0xF0) { if (ch2 < 0x90) /* invalid sequence - \xF0\x80\x80\x80-\xF0\x80\xBF\xBF -- fake 0000-FFFF */ - goto InvalidContinuation; - } - else if (ch == 0xF4 && ch2 > 0x8F) { + \xF0\x80\x80\x80-\xF0\x8F\xBF\xBF -- fake 0000-FFFF */ + goto InvalidContinuation1; + } else if (ch == 0xF4 && ch2 >= 0x90) { /* invalid sequence \xF4\x90\x80\80- -- 110000- overflow */ - goto InvalidContinuation; + goto InvalidContinuation1; + } + if (!IS_CONTINUATION_BYTE(ch3)) { + /* invalid continuation byte */ + goto InvalidContinuation2; + } + if (!IS_CONTINUATION_BYTE(ch4)) { + /* invalid continuation byte */ + goto InvalidContinuation3; } ch = (ch << 18) + (ch2 << 12) + (ch3 << 6) + ch4 - ((0xF0 << 18) + (0x80 << 12) + (0x80 << 6) + 0x80); @@ -195,14 +222,14 @@ s += 4; if (STRINGLIB_MAX_CHAR <= 0xFFFF || (STRINGLIB_MAX_CHAR < 0x10FFFF && ch > STRINGLIB_MAX_CHAR)) - goto Overflow; + /* Out-of-range */ + goto Return; *p++ = ch; continue; } goto InvalidStart; } ch = 0; -Overflow: Return: *inptr = s; *outpos = p - dest; @@ -210,13 +237,18 @@ InvalidStart: ch = 1; goto Return; -InvalidContinuation: +InvalidContinuation1: ch = 2; goto Return; +InvalidContinuation2: + ch = 3; + goto Return; +InvalidContinuation3: + ch = 4; + goto Return; } #undef ASCII_CHAR_MASK -#undef IS_CONTINUATION_BYTE /* UTF-8 encoder specialized for a Unicode kind to avoid the slow diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -4611,9 +4611,7 @@ goto End; errmsg = "unexpected end of data"; startinpos = s - starts; - endinpos = startinpos + 1; - while (endinpos < size && (starts[endinpos] & 0xC0) == 0x80) - endinpos++; + endinpos = end - starts; break; case 1: errmsg = "invalid start byte"; @@ -4621,11 +4619,11 @@ endinpos = startinpos + 1; break; case 2: + case 3: + case 4: errmsg = "invalid continuation byte"; startinpos = s - starts; - endinpos = startinpos + 1; - while (endinpos < size && (starts[endinpos] & 0xC0) == 0x80) - endinpos++; + endinpos = startinpos + ch - 1; break; default: if (unicode_putchar(&unicode, &outpos, ch) < 0) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 23:15:08 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 23:15:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzUwNTc6IHRoZSBw?= =?utf-8?q?eepholer_no_longer_optimizes_subscription_on_unicode_literals_?= =?utf-8?b?KGUuZy4=?= Message-ID: <3XvrtN26TfzRD3@mail.python.org> http://hg.python.org/cpython/rev/9481e062fe26 changeset: 80248:9481e062fe26 branch: 2.7 parent: 80232:dc96df8556d8 user: Ezio Melotti date: Mon Nov 05 00:03:21 2012 +0200 summary: #5057: the peepholer no longer optimizes subscription on unicode literals (e.g. u"foo"[0]) in order to produce compatible pyc files between narrow and wide builds. files: Lib/test/test_peepholer.py | 13 ++++++----- Misc/NEWS | 4 +++ Python/peephole.c | 27 ++++++------------------- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -138,21 +138,22 @@ self.assertIn('(1000)', asm) def test_binary_subscr_on_unicode(self): - # valid code get optimized + # unicode strings don't get optimized asm = dis_single('u"foo"[0]') - self.assertIn("(u'f')", asm) - self.assertNotIn('BINARY_SUBSCR', asm) + self.assertNotIn("(u'f')", asm) + self.assertIn('BINARY_SUBSCR', asm) asm = dis_single('u"\u0061\uffff"[1]') - self.assertIn("(u'\\uffff')", asm) - self.assertNotIn('BINARY_SUBSCR', asm) + self.assertNotIn("(u'\\uffff')", asm) + self.assertIn('BINARY_SUBSCR', asm) - # invalid code doesn't get optimized # out of range asm = dis_single('u"fuu"[10]') self.assertIn('BINARY_SUBSCR', asm) # non-BMP char (see #5057) asm = dis_single('u"\U00012345"[0]') self.assertIn('BINARY_SUBSCR', asm) + asm = dis_single('u"\U00012345abcdef"[3]') + self.assertIn('BINARY_SUBSCR', asm) def test_folding_of_unaryops_on_constants(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,10 @@ Core and Builtins ----------------- +- Issue #5057: the peepholer no longer optimize subscription on unicode + literals (e.g. u'foo'[0]) in order to produce compatible pyc files between + narrow and wide builds. + - Issue #8401: assigning an int to a bytearray slice (e.g. b[3:4] = 5) now raises an error. diff --git a/Python/peephole.c b/Python/peephole.c --- a/Python/peephole.c +++ b/Python/peephole.c @@ -128,27 +128,14 @@ newconst = PyNumber_Subtract(v, w); break; case BINARY_SUBSCR: + /* #5057: if v is unicode, there might be differences between + wide and narrow builds in cases like '\U00012345'[0] or + '\U00012345abcdef'[3], so it's better to skip the optimization + in order to produce compatible pycs. + */ + if (PyUnicode_Check(v)) + return 0; newconst = PyObject_GetItem(v, w); - /* #5057: if v is unicode, there might be differences between - wide and narrow builds in cases like u'\U00012345'[0]. - Wide builds will return a non-BMP char, whereas narrow builds - will return a surrogate. In both the cases skip the - optimization in order to produce compatible pycs. - */ -#ifdef Py_USING_UNICODE - if (newconst != NULL && - PyUnicode_Check(v) && PyUnicode_Check(newconst)) { - Py_UNICODE ch = PyUnicode_AS_UNICODE(newconst)[0]; -#ifdef Py_UNICODE_WIDE - if (ch > 0xFFFF) { -#else - if (ch >= 0xD800 && ch <= 0xDFFF) { -#endif - Py_DECREF(newconst); - return 0; - } - } -#endif break; case BINARY_LSHIFT: newconst = PyNumber_Lshift(v, w); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 23:15:09 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 23:15:09 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzUwNTc6IHRoZSBw?= =?utf-8?q?eepholer_no_longer_optimizes_subscription_on_unicode_literals_?= =?utf-8?b?KGUuZy4=?= Message-ID: <3XvrtP4vHRzRGJ@mail.python.org> http://hg.python.org/cpython/rev/56bc323288d1 changeset: 80249:56bc323288d1 branch: 3.2 parent: 80236:94d15358ad6e user: Ezio Melotti date: Mon Nov 05 00:06:32 2012 +0200 summary: #5057: the peepholer no longer optimizes subscription on unicode literals (e.g. u"foo"[0]) in order to produce compatible pyc files between narrow and wide builds. files: Lib/test/test_peepholer.py | 13 +++++++------ Misc/NEWS | 4 ++++ Python/peephole.c | 25 +++++++------------------ 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -196,21 +196,22 @@ self.assertIn('(1000)', asm) def test_binary_subscr_on_unicode(self): - # valid code get optimized + # unicode strings don't get optimized asm = dis_single('"foo"[0]') - self.assertIn("('f')", asm) - self.assertNotIn('BINARY_SUBSCR', asm) + self.assertNotIn("('f')", asm) + self.assertIn('BINARY_SUBSCR', asm) asm = dis_single('"\u0061\uffff"[1]') - self.assertIn("('\\uffff')", asm) - self.assertNotIn('BINARY_SUBSCR', asm) + self.assertNotIn("('\\uffff')", asm) + self.assertIn('BINARY_SUBSCR', asm) - # invalid code doesn't get optimized # out of range asm = dis_single('"fuu"[10]') self.assertIn('BINARY_SUBSCR', asm) # non-BMP char (see #5057) asm = dis_single('"\U00012345"[0]') self.assertIn('BINARY_SUBSCR', asm) + asm = dis_single('"\U00012345abcdef"[3]') + self.assertIn('BINARY_SUBSCR', asm) def test_folding_of_unaryops_on_constants(self): diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,10 @@ Core and Builtins ----------------- +- Issue #5057: the peepholer no longer optimizes subscription on unicode + literals (e.g. u'foo'[0]) in order to produce compatible pyc files between + narrow and wide builds. + - Issue #16402: When slicing a range, fix shadowing of exceptions from __index__. diff --git a/Python/peephole.c b/Python/peephole.c --- a/Python/peephole.c +++ b/Python/peephole.c @@ -132,25 +132,14 @@ newconst = PyNumber_Subtract(v, w); break; case BINARY_SUBSCR: + /* #5057: if v is unicode, there might be differences between + wide and narrow builds in cases like '\U00012345'[0] or + '\U00012345abcdef'[3], so it's better to skip the optimization + in order to produce compatible pycs. + */ + if (PyUnicode_Check(v)) + return 0; newconst = PyObject_GetItem(v, w); - /* #5057: if v is unicode, there might be differences between - wide and narrow builds in cases like '\U00012345'[0]. - Wide builds will return a non-BMP char, whereas narrow builds - will return a surrogate. In both the cases skip the - optimization in order to produce compatible pycs. - */ - if (newconst != NULL && - PyUnicode_Check(v) && PyUnicode_Check(newconst)) { - Py_UNICODE ch = PyUnicode_AS_UNICODE(newconst)[0]; -#ifdef Py_UNICODE_WIDE - if (ch > 0xFFFF) { -#else - if (ch >= 0xD800 && ch <= 0xDFFF) { -#endif - Py_DECREF(newconst); - return 0; - } - } break; case BINARY_LSHIFT: newconst = PyNumber_Lshift(v, w); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 23:15:10 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 23:15:10 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogRml4IHR5cG8u?= Message-ID: <3XvrtQ753rzRH2@mail.python.org> http://hg.python.org/cpython/rev/daa1a7a51319 changeset: 80250:daa1a7a51319 branch: 2.7 parent: 80248:9481e062fe26 user: Ezio Melotti date: Mon Nov 05 00:06:50 2012 +0200 summary: Fix typo. 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 @@ -9,7 +9,7 @@ Core and Builtins ----------------- -- Issue #5057: the peepholer no longer optimize subscription on unicode +- Issue #5057: the peepholer no longer optimizes subscription on unicode literals (e.g. u'foo'[0]) in order to produce compatible pyc files between narrow and wide builds. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 23:15:12 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 23:15:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=235057=3A_null_merge_with_3=2E2_=28only_add_tests=29=2E?= Message-ID: <3XvrtS2BTZzRJ5@mail.python.org> http://hg.python.org/cpython/rev/3b4f2f9272b4 changeset: 80251:3b4f2f9272b4 branch: 3.3 parent: 80246:5962f192a483 parent: 80249:56bc323288d1 user: Ezio Melotti date: Mon Nov 05 00:13:57 2012 +0200 summary: #5057: null merge with 3.2 (only add tests). files: Lib/test/test_peepholer.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -213,6 +213,9 @@ asm = dis_single('"\u0061\uffff"[1]') self.assertIn("('\\uffff')", asm) self.assertNotIn('BINARY_SUBSCR', asm) + asm = dis_single('"\U00012345abcdef"[3]') + self.assertIn("('c')", asm) + self.assertNotIn('BINARY_SUBSCR', asm) # invalid code doesn't get optimized # out of range -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Sun Nov 4 23:15:13 2012 From: python-checkins at python.org (ezio.melotti) Date: Sun, 4 Nov 2012 23:15:13 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=235057=3A_null_merge_with_3=2E3_=28only_add_tests=29=2E?= Message-ID: <3XvrtT4V0czRJH@mail.python.org> http://hg.python.org/cpython/rev/0790c16bb275 changeset: 80252:0790c16bb275 parent: 80247:5b205fff1972 parent: 80251:3b4f2f9272b4 user: Ezio Melotti date: Mon Nov 05 00:14:34 2012 +0200 summary: #5057: null merge with 3.3 (only add tests). files: Lib/test/test_peepholer.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -213,6 +213,9 @@ asm = dis_single('"\u0061\uffff"[1]') self.assertIn("('\\uffff')", asm) self.assertNotIn('BINARY_SUBSCR', asm) + asm = dis_single('"\U00012345abcdef"[3]') + self.assertIn("('c')", asm) + self.assertNotIn('BINARY_SUBSCR', asm) # invalid code doesn't get optimized # out of range -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 00:00:40 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 5 Nov 2012 00:00:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzgyNzE6?= =?utf-8?q?_Fix_compilation_on_Windows?= Message-ID: <3Xvstw2D7lzRFR@mail.python.org> http://hg.python.org/cpython/rev/96f4cee8ea5e changeset: 80253:96f4cee8ea5e branch: 3.3 parent: 80251:3b4f2f9272b4 user: Victor Stinner date: Sun Nov 04 23:59:15 2012 +0100 summary: Issue #8271: Fix compilation on Windows files: Objects/stringlib/codecs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -93,13 +93,13 @@ if (ch < 0xE0) { /* \xC2\x80-\xDF\xBF -- 0080-07FF */ + Py_UCS4 ch2; if (ch < 0xC2) { /* invalid sequence \x80-\xBF -- continuation byte \xC0-\xC1 -- fake 0000-007F */ goto InvalidStart; } - Py_UCS4 ch2; if (end - s < 2) { /* unexpected end of data: the caller will decide whether it's an error or not */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 00:00:41 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 5 Nov 2012 00:00:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=28Merge_3=2E3=29_Issue_=238271=3A_Fix_compilation_on_Wi?= =?utf-8?q?ndows?= Message-ID: <3Xvstx4MR2zRGC@mail.python.org> http://hg.python.org/cpython/rev/6f44f33460cd changeset: 80254:6f44f33460cd parent: 80252:0790c16bb275 parent: 80253:96f4cee8ea5e user: Victor Stinner date: Mon Nov 05 00:00:50 2012 +0100 summary: (Merge 3.3) Issue #8271: Fix compilation on Windows files: Objects/stringlib/codecs.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Objects/stringlib/codecs.h b/Objects/stringlib/codecs.h --- a/Objects/stringlib/codecs.h +++ b/Objects/stringlib/codecs.h @@ -93,13 +93,13 @@ if (ch < 0xE0) { /* \xC2\x80-\xDF\xBF -- 0080-07FF */ + Py_UCS4 ch2; if (ch < 0xC2) { /* invalid sequence \x80-\xBF -- continuation byte \xC0-\xC1 -- fake 0000-007F */ goto InvalidStart; } - Py_UCS4 ch2; if (end - s < 2) { /* unexpected end of data: the caller will decide whether it's an error or not */ -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 00:44:28 2012 From: python-checkins at python.org (nadeem.vawda) Date: Mon, 5 Nov 2012 00:44:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE2MzUw?= =?utf-8?q?=3A_Fix_zlib_decompressor_handling_of_unused=5Fdata_with_multip?= =?utf-8?q?le_calls?= Message-ID: <3XvtsS3xJFzQ2J@mail.python.org> http://hg.python.org/cpython/rev/be882735e0b6 changeset: 80255:be882735e0b6 branch: 3.2 parent: 80249:56bc323288d1 user: Nadeem Vawda date: Mon Nov 05 00:37:42 2012 +0100 summary: Issue #16350: Fix zlib decompressor handling of unused_data with multiple calls to decompress() after EOF. Patch by Serhiy Storchaka. files: Lib/test/test_zlib.py | 13 +++++++++++++ Misc/NEWS | 4 ++++ Modules/zlibmodule.c | 29 +++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -434,6 +434,19 @@ y += dco.flush() self.assertEqual(y, b'foo') + def test_decompress_unused_data(self): + # Repeated calls to decompress() after EOF should accumulate data in + # dco.unused_data, instead of just storing the arg to the last call. + x = zlib.compress(HAMLET_SCENE) + HAMLET_SCENE + for step in 1, 2, 100: + dco = zlib.decompressobj() + data = b''.join(dco.decompress(x[i : i + step]) + for i in range(0, len(x), step)) + data += dco.flush() + + self.assertEqual(data, HAMLET_SCENE) + self.assertEqual(dco.unused_data, HAMLET_SCENE) + if hasattr(zlib.compressobj(), "copy"): def test_compresscopy(self): # Test copying a compression object diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -156,6 +156,10 @@ Library ------- +- Issue #16350: zlib.Decompress.decompress() now accumulates data from + successive calls after EOF in unused_data, instead of only saving the argument + to the last call. Patch by Serhiy Storchaka. + - Issue #12759: sre_parse now raises a proper error when the name of the group is missing. Initial patch by Serhiy Storchaka. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -610,12 +610,29 @@ preserved. */ if (err == Z_STREAM_END) { - Py_XDECREF(self->unused_data); /* Free original empty string */ - self->unused_data = PyBytes_FromStringAndSize( - (char *)self->zst.next_in, self->zst.avail_in); - if (self->unused_data == NULL) { - Py_DECREF(RetVal); - goto error; + if (self->zst.avail_in > 0) { + /* Append the leftover data to the existing value of unused_data. */ + Py_ssize_t old_size = PyBytes_GET_SIZE(self->unused_data); + Py_ssize_t new_size = old_size + self->zst.avail_in; + PyObject *new_data; + if (new_size <= old_size) { /* Check for overflow. */ + PyErr_NoMemory(); + Py_DECREF(RetVal); + RetVal = NULL; + goto error; + } + new_data = PyBytes_FromStringAndSize(NULL, new_size); + if (new_data == NULL) { + Py_DECREF(RetVal); + RetVal = NULL; + goto error; + } + Py_MEMCPY(PyBytes_AS_STRING(new_data), + PyBytes_AS_STRING(self->unused_data), old_size); + Py_MEMCPY(PyBytes_AS_STRING(new_data) + old_size, + self->zst.next_in, self->zst.avail_in); + Py_DECREF(self->unused_data); + self->unused_data = new_data; } /* We will only get Z_BUF_ERROR if the output buffer was full but there wasn't more output when we tried again, so it is -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 00:44:29 2012 From: python-checkins at python.org (nadeem.vawda) Date: Mon, 5 Nov 2012 00:44:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2316350=3A_Fix_zlib_decompressor_handling_of_unused=5Fd?= =?utf-8?q?ata_with_multiple_calls?= Message-ID: <3XvtsT6Dx3zQ2J@mail.python.org> http://hg.python.org/cpython/rev/4182119c3f0a changeset: 80256:4182119c3f0a branch: 3.3 parent: 80253:96f4cee8ea5e parent: 80255:be882735e0b6 user: Nadeem Vawda date: Mon Nov 05 00:38:48 2012 +0100 summary: Issue #16350: Fix zlib decompressor handling of unused_data with multiple calls to decompress() after EOF. Patch by Serhiy Storchaka. files: Lib/test/test_zlib.py | 14 ++++++++++++++ Misc/NEWS | 4 ++++ Modules/zlibmodule.c | 29 +++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -487,6 +487,20 @@ dco.flush() self.assertFalse(dco.eof) + def test_decompress_unused_data(self): + # Repeated calls to decompress() after EOF should accumulate data in + # dco.unused_data, instead of just storing the arg to the last call. + x = zlib.compress(HAMLET_SCENE) + HAMLET_SCENE + for step in 1, 2, 100: + dco = zlib.decompressobj() + data = b''.join(dco.decompress(x[i : i + step]) + for i in range(0, len(x), step)) + data += dco.flush() + + self.assertTrue(dco.eof) + self.assertEqual(data, HAMLET_SCENE) + self.assertEqual(dco.unused_data, HAMLET_SCENE) + if hasattr(zlib.compressobj(), "copy"): def test_compresscopy(self): # Test copying a compression object diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -77,6 +77,10 @@ Library ------- +- Issue #16350: zlib.Decompress.decompress() now accumulates data from + successive calls after EOF in unused_data, instead of only saving the argument + to the last call. Patch by Serhiy Storchaka. + - Issue #12759: sre_parse now raises a proper error when the name of the group is missing. Initial patch by Serhiy Storchaka. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -693,12 +693,29 @@ preserved. */ if (err == Z_STREAM_END) { - Py_XDECREF(self->unused_data); /* Free original empty string */ - self->unused_data = PyBytes_FromStringAndSize( - (char *)self->zst.next_in, self->zst.avail_in); - if (self->unused_data == NULL) { - Py_DECREF(RetVal); - goto error; + if (self->zst.avail_in > 0) { + /* Append the leftover data to the existing value of unused_data. */ + Py_ssize_t old_size = PyBytes_GET_SIZE(self->unused_data); + Py_ssize_t new_size = old_size + self->zst.avail_in; + PyObject *new_data; + if (new_size <= old_size) { /* Check for overflow. */ + PyErr_NoMemory(); + Py_DECREF(RetVal); + RetVal = NULL; + goto error; + } + new_data = PyBytes_FromStringAndSize(NULL, new_size); + if (new_data == NULL) { + Py_DECREF(RetVal); + RetVal = NULL; + goto error; + } + Py_MEMCPY(PyBytes_AS_STRING(new_data), + PyBytes_AS_STRING(self->unused_data), old_size); + Py_MEMCPY(PyBytes_AS_STRING(new_data) + old_size, + self->zst.next_in, self->zst.avail_in); + Py_DECREF(self->unused_data); + self->unused_data = new_data; } self->eof = 1; /* We will only get Z_BUF_ERROR if the output buffer was full -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 00:44:31 2012 From: python-checkins at python.org (nadeem.vawda) Date: Mon, 5 Nov 2012 00:44:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2316350=3A_Fix_zlib_decompressor_handling_of_unus?= =?utf-8?q?ed=5Fdata_with_multiple_calls?= Message-ID: <3XvtsW1mJczRD0@mail.python.org> http://hg.python.org/cpython/rev/bcdb3836be72 changeset: 80257:bcdb3836be72 parent: 80254:6f44f33460cd parent: 80256:4182119c3f0a user: Nadeem Vawda date: Mon Nov 05 00:40:00 2012 +0100 summary: Issue #16350: Fix zlib decompressor handling of unused_data with multiple calls to decompress() after EOF. Patch by Serhiy Storchaka. files: Lib/test/test_zlib.py | 14 ++++++++++++++ Misc/NEWS | 4 ++++ Modules/zlibmodule.c | 29 +++++++++++++++++++++++------ 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -487,6 +487,20 @@ dco.flush() self.assertFalse(dco.eof) + def test_decompress_unused_data(self): + # Repeated calls to decompress() after EOF should accumulate data in + # dco.unused_data, instead of just storing the arg to the last call. + x = zlib.compress(HAMLET_SCENE) + HAMLET_SCENE + for step in 1, 2, 100: + dco = zlib.decompressobj() + data = b''.join(dco.decompress(x[i : i + step]) + for i in range(0, len(x), step)) + data += dco.flush() + + self.assertTrue(dco.eof) + self.assertEqual(data, HAMLET_SCENE) + self.assertEqual(dco.unused_data, HAMLET_SCENE) + if hasattr(zlib.compressobj(), "copy"): def test_compresscopy(self): # Test copying a compression object diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -107,6 +107,10 @@ Library ------- +- Issue #16350: zlib.Decompress.decompress() now accumulates data from + successive calls after EOF in unused_data, instead of only saving the argument + to the last call. Patch by Serhiy Storchaka. + - Issue #12759: sre_parse now raises a proper error when the name of the group is missing. Initial patch by Serhiy Storchaka. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -693,12 +693,29 @@ preserved. */ if (err == Z_STREAM_END) { - Py_XDECREF(self->unused_data); /* Free original empty string */ - self->unused_data = PyBytes_FromStringAndSize( - (char *)self->zst.next_in, self->zst.avail_in); - if (self->unused_data == NULL) { - Py_DECREF(RetVal); - goto error; + if (self->zst.avail_in > 0) { + /* Append the leftover data to the existing value of unused_data. */ + Py_ssize_t old_size = PyBytes_GET_SIZE(self->unused_data); + Py_ssize_t new_size = old_size + self->zst.avail_in; + PyObject *new_data; + if (new_size <= old_size) { /* Check for overflow. */ + PyErr_NoMemory(); + Py_DECREF(RetVal); + RetVal = NULL; + goto error; + } + new_data = PyBytes_FromStringAndSize(NULL, new_size); + if (new_data == NULL) { + Py_DECREF(RetVal); + RetVal = NULL; + goto error; + } + Py_MEMCPY(PyBytes_AS_STRING(new_data), + PyBytes_AS_STRING(self->unused_data), old_size); + Py_MEMCPY(PyBytes_AS_STRING(new_data) + old_size, + self->zst.next_in, self->zst.avail_in); + Py_DECREF(self->unused_data); + self->unused_data = new_data; } self->eof = 1; /* We will only get Z_BUF_ERROR if the output buffer was full -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 00:57:27 2012 From: python-checkins at python.org (nadeem.vawda) Date: Mon, 5 Nov 2012 00:57:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2MzUw?= =?utf-8?q?=3A_Fix_zlib_decompressor_handling_of_unused=5Fdata_with_multip?= =?utf-8?q?le_calls?= Message-ID: <3Xvv8R6RYtzR5Q@mail.python.org> http://hg.python.org/cpython/rev/1c54def5947c changeset: 80258:1c54def5947c branch: 2.7 parent: 80250:daa1a7a51319 user: Nadeem Vawda date: Mon Nov 05 00:55:06 2012 +0100 summary: Issue #16350: Fix zlib decompressor handling of unused_data with multiple calls to decompress() after EOF. Patch by Serhiy Storchaka. files: Lib/test/test_zlib.py | 13 +++++++++++++ Misc/NEWS | 4 ++++ Modules/zlibmodule.c | 29 +++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_zlib.py b/Lib/test/test_zlib.py --- a/Lib/test/test_zlib.py +++ b/Lib/test/test_zlib.py @@ -426,6 +426,19 @@ c.flush() self.assertRaises(ValueError, c.copy) + def test_decompress_unused_data(self): + # Repeated calls to decompress() after EOF should accumulate data in + # dco.unused_data, instead of just storing the arg to the last call. + x = zlib.compress(HAMLET_SCENE) + HAMLET_SCENE + for step in 1, 2, 100: + dco = zlib.decompressobj() + data = b''.join(dco.decompress(x[i : i + step]) + for i in range(0, len(x), step)) + data += dco.flush() + + self.assertEqual(data, HAMLET_SCENE) + self.assertEqual(dco.unused_data, HAMLET_SCENE) + if hasattr(zlib.decompressobj(), "copy"): def test_decompresscopy(self): # Test copying a decompression object diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -137,6 +137,10 @@ Library ------- +- Issue #16350: zlib.Decompress.decompress() now accumulates data from + successive calls after EOF in unused_data, instead of only saving the argument + to the last call. Patch by Serhiy Storchaka. + - Issue #12759: sre_parse now raises a proper error when the name of the group is missing. Initial patch by Serhiy Storchaka. diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c --- a/Modules/zlibmodule.c +++ b/Modules/zlibmodule.c @@ -566,12 +566,29 @@ preserved. */ if (err == Z_STREAM_END) { - Py_XDECREF(self->unused_data); /* Free original empty string */ - self->unused_data = PyString_FromStringAndSize( - (char *)self->zst.next_in, self->zst.avail_in); - if (self->unused_data == NULL) { - Py_DECREF(RetVal); - goto error; + if (self->zst.avail_in > 0) { + /* Append the leftover data to the existing value of unused_data. */ + Py_ssize_t old_size = PyString_GET_SIZE(self->unused_data); + Py_ssize_t new_size = old_size + self->zst.avail_in; + PyObject *new_data; + if (new_size <= old_size) { /* Check for overflow. */ + PyErr_NoMemory(); + Py_DECREF(RetVal); + RetVal = NULL; + goto error; + } + new_data = PyString_FromStringAndSize(NULL, new_size); + if (new_data == NULL) { + Py_DECREF(RetVal); + RetVal = NULL; + goto error; + } + Py_MEMCPY(PyString_AS_STRING(new_data), + PyString_AS_STRING(self->unused_data), old_size); + Py_MEMCPY(PyString_AS_STRING(new_data) + old_size, + self->zst.next_in, self->zst.avail_in); + Py_DECREF(self->unused_data); + self->unused_data = new_data; } /* We will only get Z_BUF_ERROR if the output buffer was full but there wasn't more output when we tried again, so it is -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 01:21:14 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 5 Nov 2012 01:21:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315478=3A_Oops=2C_?= =?utf-8?q?fix_regression_in_os=2Eopen=28=29_on_Windows?= Message-ID: <3Xvvgt3cq6zR94@mail.python.org> http://hg.python.org/cpython/rev/817a90752470 changeset: 80259:817a90752470 parent: 80257:bcdb3836be72 user: Victor Stinner date: Mon Nov 05 01:20:58 2012 +0100 summary: Issue #15478: Oops, fix regression in os.open() on Windows os.open() uses _wopen() which sets errno, not the Windows error code. files: Modules/posixmodule.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -7057,7 +7057,7 @@ Py_END_ALLOW_THREADS if (fd == -1) { - return_value = path_error(&path); + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, path.object); goto exit; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 01:28:17 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 5 Nov 2012 01:28:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315478=3A_Fix_test?= =?utf-8?q?=5Fpep277_on_Windows?= Message-ID: <3Xvvr16xSZzPjB@mail.python.org> http://hg.python.org/cpython/rev/11ea4eb79e9d changeset: 80260:11ea4eb79e9d user: Victor Stinner date: Mon Nov 05 01:28:28 2012 +0100 summary: Issue #15478: Fix test_pep277 on Windows os.listdir() now returns the original path in OSError.filename (on any platform), even if "*.*" was added to the path (on Windows). files: Lib/test/test_pep277.py | 4 ---- 1 files changed, 0 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_pep277.py b/Lib/test/test_pep277.py --- a/Lib/test/test_pep277.py +++ b/Lib/test/test_pep277.py @@ -99,10 +99,6 @@ with self.assertRaises(expected_exception) as c: fn(filename) exc_filename = c.exception.filename - # listdir may append a wildcard to the filename - if fn is os.listdir and sys.platform == 'win32': - exc_filename, _, wildcard = exc_filename.rpartition(os.sep) - self.assertEqual(wildcard, '*.*') if check_filename: self.assertEqual(exc_filename, filename, "Function '%s(%a) failed " "with bad filename in the exception: %a" % -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 02:06:24 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 5 Nov 2012 02:06:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogQ2xvc2UgIzE1MTY1?= =?utf-8?q?=3A_Fix_test=5Femail_on_Windows_64_bits?= Message-ID: <3Xvwh019xfzRCB@mail.python.org> http://hg.python.org/cpython/rev/367e376e5ba2 changeset: 80261:367e376e5ba2 branch: 3.3 parent: 80256:4182119c3f0a user: Victor Stinner date: Mon Nov 05 02:06:13 2012 +0100 summary: Close #15165: Fix test_email on Windows 64 bits Use year 1990 instead of year 1970 to avoid issues with negative timestamps. files: Lib/test/test_email/test_utils.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -91,7 +91,7 @@ @test.support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0') def test_localtime_epoch_utc_daylight_true(self): test.support.patch(self, time, 'daylight', True) - t0 = datetime.datetime(1970, 1, 1, tzinfo = datetime.timezone.utc) + t0 = datetime.datetime(1990, 1, 1, tzinfo = datetime.timezone.utc) t1 = utils.localtime(t0) t2 = t0 - datetime.timedelta(hours=5) t2 = t2.replace(tzinfo = datetime.timezone(datetime.timedelta(hours=-5))) @@ -100,7 +100,7 @@ @test.support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0') def test_localtime_epoch_utc_daylight_false(self): test.support.patch(self, time, 'daylight', False) - t0 = datetime.datetime(1970, 1, 1, tzinfo = datetime.timezone.utc) + t0 = datetime.datetime(1990, 1, 1, tzinfo = datetime.timezone.utc) t1 = utils.localtime(t0) t2 = t0 - datetime.timedelta(hours=5) t2 = t2.replace(tzinfo = datetime.timezone(datetime.timedelta(hours=-5))) @@ -108,14 +108,14 @@ def test_localtime_epoch_notz_daylight_true(self): test.support.patch(self, time, 'daylight', True) - t0 = datetime.datetime(1970, 1, 1) + t0 = datetime.datetime(1990, 1, 1) t1 = utils.localtime(t0) t2 = utils.localtime(t0.replace(tzinfo=None)) self.assertEqual(t1, t2) def test_localtime_epoch_notz_daylight_false(self): test.support.patch(self, time, 'daylight', False) - t0 = datetime.datetime(1970, 1, 1) + t0 = datetime.datetime(1990, 1, 1) t1 = utils.localtime(t0) t2 = utils.localtime(t0.replace(tzinfo=None)) self.assertEqual(t1, t2) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 02:06:25 2012 From: python-checkins at python.org (victor.stinner) Date: Mon, 5 Nov 2012 02:06:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_=28Merge_3=2E3=29_Close_=2315165=3A_Fix_test=5Femail_on_?= =?utf-8?q?Windows_64_bits?= Message-ID: <3Xvwh13xpgzRGK@mail.python.org> http://hg.python.org/cpython/rev/651e8613e579 changeset: 80262:651e8613e579 parent: 80260:11ea4eb79e9d parent: 80261:367e376e5ba2 user: Victor Stinner date: Mon Nov 05 02:06:34 2012 +0100 summary: (Merge 3.3) Close #15165: Fix test_email on Windows 64 bits Use year 1990 instead of year 1970 to avoid issues with negative timestamps. files: Lib/test/test_email/test_utils.py | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_email/test_utils.py b/Lib/test/test_email/test_utils.py --- a/Lib/test/test_email/test_utils.py +++ b/Lib/test/test_email/test_utils.py @@ -91,7 +91,7 @@ @test.support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0') def test_localtime_epoch_utc_daylight_true(self): test.support.patch(self, time, 'daylight', True) - t0 = datetime.datetime(1970, 1, 1, tzinfo = datetime.timezone.utc) + t0 = datetime.datetime(1990, 1, 1, tzinfo = datetime.timezone.utc) t1 = utils.localtime(t0) t2 = t0 - datetime.timedelta(hours=5) t2 = t2.replace(tzinfo = datetime.timezone(datetime.timedelta(hours=-5))) @@ -100,7 +100,7 @@ @test.support.run_with_tz('EST+05EDT,M3.2.0,M11.1.0') def test_localtime_epoch_utc_daylight_false(self): test.support.patch(self, time, 'daylight', False) - t0 = datetime.datetime(1970, 1, 1, tzinfo = datetime.timezone.utc) + t0 = datetime.datetime(1990, 1, 1, tzinfo = datetime.timezone.utc) t1 = utils.localtime(t0) t2 = t0 - datetime.timedelta(hours=5) t2 = t2.replace(tzinfo = datetime.timezone(datetime.timedelta(hours=-5))) @@ -108,14 +108,14 @@ def test_localtime_epoch_notz_daylight_true(self): test.support.patch(self, time, 'daylight', True) - t0 = datetime.datetime(1970, 1, 1) + t0 = datetime.datetime(1990, 1, 1) t1 = utils.localtime(t0) t2 = utils.localtime(t0.replace(tzinfo=None)) self.assertEqual(t1, t2) def test_localtime_epoch_notz_daylight_false(self): test.support.patch(self, time, 'daylight', False) - t0 = datetime.datetime(1970, 1, 1) + t0 = datetime.datetime(1990, 1, 1) t1 = utils.localtime(t0) t2 = utils.localtime(t0.replace(tzinfo=None)) self.assertEqual(t1, t2) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Mon Nov 5 05:54:27 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Mon, 05 Nov 2012 05:54:27 +0100 Subject: [Python-checkins] Daily reference leaks (651e8613e579): sum=0 Message-ID: results for 651e8613e579 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogOOmNS6', '-x'] From python-checkins at python.org Mon Nov 5 07:20:25 2012 From: python-checkins at python.org (andrew.svetlov) Date: Mon, 5 Nov 2012 07:20:25 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316218=3A_Fix_test?= =?utf-8?q?_for_issue_again?= Message-ID: <3Xw3fK6lpqzRHX@mail.python.org> http://hg.python.org/cpython/rev/56df0d4f0011 changeset: 80263:56df0d4f0011 user: Andrew Svetlov date: Mon Nov 05 08:20:15 2012 +0200 summary: Issue #16218: Fix test for issue again files: Lib/test/test_cmd_line_script.py | 37 ++++++++++--------- 1 files changed, 19 insertions(+), 18 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -363,25 +363,26 @@ self.assertTrue(text[1].startswith(' File ')) self.assertTrue(text[3].startswith('NameError')) - def test_non_utf8(self): + def test_non_ascii(self): # Issue #16218 - with temp_dir() as script_dir: - script_basename = '\u0441\u043a\u0440\u0438\u043f\u0442' - try: - script_basename.encode(sys.getfilesystemencoding()) - except UnicodeEncodeError: - raise unittest.SkipTest("Filesystem doesn't support " - "unicode names") - source = 'print("test output")\n' - script_name = _make_test_script(script_dir, script_basename, source) - if not __debug__: - run_args = ('-' + 'O' * sys.flags.optimize, script_name) - else: - run_args = (script_name,) - rc, out, _ = assert_python_ok(*run_args) - self.assertEqual(0, rc) - expected = ("test output" + os.linesep).encode('ascii') - self.assertEqual(expected, out) + # non-ascii filename encodable to cp1252, cp932, latin1 and utf8 + filename = support.TESTFN + '\xa3.py' + try: + os.fsencode(filename) + except UnicodeEncodeError: + self.skipTest( + "Filesystem encoding %r cannot encode " + "the filename: %a" + % (sys.getfilesystemencoding(), filename)) + source = 'print(ascii(__file__))\n' + script_name = _make_test_script(os.curdir, filename, source) + self.addCleanup(support.unlink, script_name) + rc, stdout, stderr = assert_python_ok(script_name) + self.assertEqual( + ascii(script_name), + stdout.rstrip().decode('ascii'), + 'stdout=%r stderr=%r' % (stdout, stderr)) + self.assertEqual(0, rc) def test_main(): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 08:28:54 2012 From: python-checkins at python.org (andrew.svetlov) Date: Mon, 5 Nov 2012 08:28:54 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Revome_extra_=2Epy_suffix?= Message-ID: <3Xw59L0dvSzRQH@mail.python.org> http://hg.python.org/cpython/rev/141852a8697a changeset: 80264:141852a8697a user: Andrew Svetlov date: Mon Nov 05 09:28:42 2012 +0200 summary: Revome extra .py suffix files: Lib/test/test_cmd_line_script.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -366,7 +366,7 @@ def test_non_ascii(self): # Issue #16218 # non-ascii filename encodable to cp1252, cp932, latin1 and utf8 - filename = support.TESTFN + '\xa3.py' + filename = support.TESTFN + '\xa3' try: os.fsencode(filename) except UnicodeEncodeError: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 08:34:57 2012 From: python-checkins at python.org (andrew.svetlov) Date: Mon, 5 Nov 2012 08:34:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2315641=3A_Clean_up?= =?utf-8?q?_deprecated_classes_from_importlib?= Message-ID: <3Xw5JK4XjNzRPk@mail.python.org> http://hg.python.org/cpython/rev/48228fb874c1 changeset: 80265:48228fb874c1 user: Andrew Svetlov date: Mon Nov 05 09:34:46 2012 +0200 summary: Issue #15641: Clean up deprecated classes from importlib Patch by Taras Lyapun. files: Doc/library/importlib.rst | 138 -- Lib/importlib/abc.py | 177 --- Lib/test/test_importlib/source/test_abc_loader.py | 505 +--------- Lib/test/test_importlib/test_abc.py | 18 +- Misc/NEWS | 3 + 5 files changed, 7 insertions(+), 834 deletions(-) diff --git a/Doc/library/importlib.rst b/Doc/library/importlib.rst --- a/Doc/library/importlib.rst +++ b/Doc/library/importlib.rst @@ -133,8 +133,6 @@ +-- ExecutionLoader --+ +-- FileLoader +-- SourceLoader - +-- PyLoader (deprecated) - +-- PyPycLoader (deprecated) .. class:: Finder @@ -431,142 +429,6 @@ itself does not end in ``__init__``. -.. class:: PyLoader - - An abstract base class inheriting from - :class:`ExecutionLoader` and - :class:`ResourceLoader` designed to ease the loading of - Python source modules (bytecode is not handled; see - :class:`SourceLoader` for a source/bytecode ABC). A subclass - implementing this ABC will only need to worry about exposing how the source - code is stored; all other details for loading Python source code will be - handled by the concrete implementations of key methods. - - .. deprecated:: 3.2 - This class has been deprecated in favor of :class:`SourceLoader` and is - slated for removal in Python 3.4. See below for how to create a - subclass that is compatible with Python 3.1 onwards. - - If compatibility with Python 3.1 is required, then use the following idiom - to implement a subclass that will work with Python 3.1 onwards (make sure - to implement :meth:`ExecutionLoader.get_filename`):: - - try: - from importlib.abc import SourceLoader - except ImportError: - from importlib.abc import PyLoader as SourceLoader - - - class CustomLoader(SourceLoader): - def get_filename(self, fullname): - """Return the path to the source file.""" - # Implement ... - - def source_path(self, fullname): - """Implement source_path in terms of get_filename.""" - try: - return self.get_filename(fullname) - except ImportError: - return None - - def is_package(self, fullname): - """Implement is_package by looking for an __init__ file - name as returned by get_filename.""" - filename = os.path.basename(self.get_filename(fullname)) - return os.path.splitext(filename)[0] == '__init__' - - - .. method:: source_path(fullname) - - An abstract method that returns the path to the source code for a - module. Should return ``None`` if there is no source code. - Raises :exc:`ImportError` if the loader knows it cannot handle the - module. - - .. method:: get_filename(fullname) - - A concrete implementation of - :meth:`importlib.abc.ExecutionLoader.get_filename` that - relies on :meth:`source_path`. If :meth:`source_path` returns - ``None``, then :exc:`ImportError` is raised. - - .. method:: load_module(fullname) - - A concrete implementation of :meth:`importlib.abc.Loader.load_module` - that loads Python source code. All needed information comes from the - abstract methods required by this ABC. The only pertinent assumption - made by this method is that when loading a package - :attr:`__path__` is set to ``[os.path.dirname(__file__)]``. - - .. method:: get_code(fullname) - - A concrete implementation of - :meth:`importlib.abc.InspectLoader.get_code` that creates code objects - from Python source code, by requesting the source code (using - :meth:`source_path` and :meth:`get_data`) and compiling it with the - built-in :func:`compile` function. - - .. method:: get_source(fullname) - - A concrete implementation of - :meth:`importlib.abc.InspectLoader.get_source`. Uses - :meth:`importlib.abc.ResourceLoader.get_data` and :meth:`source_path` - to get the source code. It tries to guess the source encoding using - :func:`tokenize.detect_encoding`. - - -.. class:: PyPycLoader - - An abstract base class inheriting from :class:`PyLoader`. - This ABC is meant to help in creating loaders that support both Python - source and bytecode. - - .. deprecated:: 3.2 - This class has been deprecated in favor of :class:`SourceLoader` and to - properly support :pep:`3147`. If compatibility is required with - Python 3.1, implement both :class:`SourceLoader` and :class:`PyLoader`; - instructions on how to do so are included in the documentation for - :class:`PyLoader`. Do note that this solution will not support - sourceless/bytecode-only loading; only source *and* bytecode loading. - - .. versionchanged:: 3.3 - Updated to parse (but not use) the new source size field in bytecode - files when reading and to write out the field properly when writing. - - .. method:: source_mtime(fullname) - - An abstract method which returns the modification time for the source - code of the specified module. The modification time should be an - integer. If there is no source code, return ``None``. If the - module cannot be found then :exc:`ImportError` is raised. - - .. method:: bytecode_path(fullname) - - An abstract method which returns the path to the bytecode for the - specified module, if it exists. It returns ``None`` - if no bytecode exists (yet). - Raises :exc:`ImportError` if the loader knows it cannot handle the - module. - - .. method:: get_filename(fullname) - - A concrete implementation of - :meth:`ExecutionLoader.get_filename` that relies on - :meth:`PyLoader.source_path` and :meth:`bytecode_path`. - If :meth:`source_path` returns a path, then that value is returned. - Else if :meth:`bytecode_path` returns a path, that path will be - returned. If a path is not available from both methods, - :exc:`ImportError` is raised. - - .. method:: write_bytecode(fullname, bytecode) - - An abstract method which has the loader write *bytecode* for future - use. If the bytecode is written, return ``True``. Return - ``False`` if the bytecode could not be written. This method - should not be called if :data:`sys.dont_write_bytecode` is true. - The *bytecode* argument should be a bytes string or bytes array. - - :mod:`importlib.machinery` -- Importers and path hooks ------------------------------------------------------ diff --git a/Lib/importlib/abc.py b/Lib/importlib/abc.py --- a/Lib/importlib/abc.py +++ b/Lib/importlib/abc.py @@ -225,180 +225,3 @@ raise NotImplementedError _register(SourceLoader, machinery.SourceFileLoader) - -class PyLoader(SourceLoader): - - """Implement the deprecated PyLoader ABC in terms of SourceLoader. - - This class has been deprecated! It is slated for removal in Python 3.4. - If compatibility with Python 3.1 is not needed then implement the - SourceLoader ABC instead of this class. If Python 3.1 compatibility is - needed, then use the following idiom to have a single class that is - compatible with Python 3.1 onwards:: - - try: - from importlib.abc import SourceLoader - except ImportError: - from importlib.abc import PyLoader as SourceLoader - - - class CustomLoader(SourceLoader): - def get_filename(self, fullname): - # Implement ... - - def source_path(self, fullname): - '''Implement source_path in terms of get_filename.''' - try: - return self.get_filename(fullname) - except ImportError: - return None - - def is_package(self, fullname): - filename = os.path.basename(self.get_filename(fullname)) - return os.path.splitext(filename)[0] == '__init__' - - """ - - @abc.abstractmethod - def is_package(self, fullname): - raise NotImplementedError - - @abc.abstractmethod - def source_path(self, fullname): - """Abstract method. Accepts a str module name and returns the path to - the source code for the module.""" - raise NotImplementedError - - def get_filename(self, fullname): - """Implement get_filename in terms of source_path. - - As get_filename should only return a source file path there is no - chance of the path not existing but loading still being possible, so - ImportError should propagate instead of being turned into returning - None. - - """ - warnings.warn("importlib.abc.PyLoader is deprecated and is " - "slated for removal in Python 3.4; " - "use SourceLoader instead. " - "See the importlib documentation on how to be " - "compatible with Python 3.1 onwards.", - DeprecationWarning) - path = self.source_path(fullname) - if path is None: - raise ImportError(name=fullname) - else: - return path - - -class PyPycLoader(PyLoader): - - """Abstract base class to assist in loading source and bytecode by - requiring only back-end storage methods to be implemented. - - This class has been deprecated! Removal is slated for Python 3.4. Implement - the SourceLoader ABC instead. If Python 3.1 compatibility is needed, see - PyLoader. - - The methods get_code, get_source, and load_module are implemented for the - user. - - """ - - def get_filename(self, fullname): - """Return the source or bytecode file path.""" - path = self.source_path(fullname) - if path is not None: - return path - path = self.bytecode_path(fullname) - if path is not None: - return path - raise ImportError("no source or bytecode path available for " - "{0!r}".format(fullname), name=fullname) - - def get_code(self, fullname): - """Get a code object from source or bytecode.""" - warnings.warn("importlib.abc.PyPycLoader is deprecated and slated for " - "removal in Python 3.4; use SourceLoader instead. " - "If Python 3.1 compatibility is required, see the " - "latest documentation for PyLoader.", - DeprecationWarning) - source_timestamp = self.source_mtime(fullname) - # Try to use bytecode if it is available. - bytecode_path = self.bytecode_path(fullname) - if bytecode_path: - data = self.get_data(bytecode_path) - try: - magic = data[:4] - if len(magic) < 4: - raise ImportError( - "bad magic number in {}".format(fullname), - name=fullname, path=bytecode_path) - raw_timestamp = data[4:8] - if len(raw_timestamp) < 4: - raise EOFError("bad timestamp in {}".format(fullname)) - pyc_timestamp = _bootstrap._r_long(raw_timestamp) - raw_source_size = data[8:12] - if len(raw_source_size) != 4: - raise EOFError("bad file size in {}".format(fullname)) - # Source size is unused as the ABC does not provide a way to - # get the size of the source ahead of reading it. - bytecode = data[12:] - # Verify that the magic number is valid. - if imp.get_magic() != magic: - raise ImportError( - "bad magic number in {}".format(fullname), - name=fullname, path=bytecode_path) - # Verify that the bytecode is not stale (only matters when - # there is source to fall back on. - if source_timestamp: - if pyc_timestamp < source_timestamp: - raise ImportError("bytecode is stale", name=fullname, - path=bytecode_path) - except (ImportError, EOFError): - # If source is available give it a shot. - if source_timestamp is not None: - pass - else: - raise - else: - # Bytecode seems fine, so try to use it. - return marshal.loads(bytecode) - elif source_timestamp is None: - raise ImportError("no source or bytecode available to create code " - "object for {0!r}".format(fullname), - name=fullname) - # Use the source. - source_path = self.source_path(fullname) - if source_path is None: - message = "a source path must exist to load {0}".format(fullname) - raise ImportError(message, name=fullname) - source = self.get_data(source_path) - code_object = compile(source, source_path, 'exec', dont_inherit=True) - # Generate bytecode and write it out. - if not sys.dont_write_bytecode: - data = bytearray(imp.get_magic()) - data.extend(_bootstrap._w_long(source_timestamp)) - data.extend(_bootstrap._w_long(len(source) & 0xFFFFFFFF)) - data.extend(marshal.dumps(code_object)) - self.write_bytecode(fullname, data) - return code_object - - @abc.abstractmethod - def source_mtime(self, fullname): - """Abstract method. Accepts a str filename and returns an int - modification time for the source of the module.""" - raise NotImplementedError - - @abc.abstractmethod - def bytecode_path(self, fullname): - """Abstract method. Accepts a str filename and returns the str pathname - to the bytecode for the module.""" - raise NotImplementedError - - @abc.abstractmethod - def write_bytecode(self, fullname, bytecode): - """Abstract method. Accepts a str filename and bytes object - representing the bytecode for the module. Returns a boolean - representing whether the bytecode was written or not.""" - raise NotImplementedError diff --git a/Lib/test/test_importlib/source/test_abc_loader.py b/Lib/test/test_importlib/source/test_abc_loader.py --- a/Lib/test/test_importlib/source/test_abc_loader.py +++ b/Lib/test/test_importlib/source/test_abc_loader.py @@ -70,483 +70,9 @@ return path == self.bytecode_path -class PyLoaderMock(abc.PyLoader): - - # Globals that should be defined for all modules. - source = (b"_ = '::'.join([__name__, __file__, __package__, " - b"repr(__loader__)])") - - def __init__(self, data): - """Take a dict of 'module_name: path' pairings. - - Paths should have no file extension, allowing packages to be denoted by - ending in '__init__'. - - """ - self.module_paths = data - self.path_to_module = {val:key for key,val in data.items()} - - def get_data(self, path): - if path not in self.path_to_module: - raise IOError - return self.source - - def is_package(self, name): - filename = os.path.basename(self.get_filename(name)) - return os.path.splitext(filename)[0] == '__init__' - - def source_path(self, name): - try: - return self.module_paths[name] - except KeyError: - raise ImportError - - def get_filename(self, name): - """Silence deprecation warning.""" - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - path = super().get_filename(name) - assert len(w) == 1 - assert issubclass(w[0].category, DeprecationWarning) - return path - - def module_repr(self): - return '' - - -class PyLoaderCompatMock(PyLoaderMock): - - """Mock that matches what is suggested to have a loader that is compatible - from Python 3.1 onwards.""" - - def get_filename(self, fullname): - try: - return self.module_paths[fullname] - except KeyError: - raise ImportError - - def source_path(self, fullname): - try: - return self.get_filename(fullname) - except ImportError: - return None - - -class PyPycLoaderMock(abc.PyPycLoader, PyLoaderMock): - - default_mtime = 1 - - def __init__(self, source, bc={}): - """Initialize mock. - - 'bc' is a dict keyed on a module's name. The value is dict with - possible keys of 'path', 'mtime', 'magic', and 'bc'. Except for 'path', - each of those keys control if any part of created bytecode is to - deviate from default values. - - """ - super().__init__(source) - self.module_bytecode = {} - self.path_to_bytecode = {} - self.bytecode_to_path = {} - for name, data in bc.items(): - self.path_to_bytecode[data['path']] = name - self.bytecode_to_path[name] = data['path'] - magic = data.get('magic', imp.get_magic()) - mtime = importlib._w_long(data.get('mtime', self.default_mtime)) - source_size = importlib._w_long(len(self.source) & 0xFFFFFFFF) - if 'bc' in data: - bc = data['bc'] - else: - bc = self.compile_bc(name) - self.module_bytecode[name] = magic + mtime + source_size + bc - - def compile_bc(self, name): - source_path = self.module_paths.get(name, '') or '' - code = compile(self.source, source_path, 'exec') - return marshal.dumps(code) - - def source_mtime(self, name): - if name in self.module_paths: - return self.default_mtime - elif name in self.module_bytecode: - return None - else: - raise ImportError - - def bytecode_path(self, name): - try: - return self.bytecode_to_path[name] - except KeyError: - if name in self.module_paths: - return None - else: - raise ImportError - - def write_bytecode(self, name, bytecode): - self.module_bytecode[name] = bytecode - return True - - def get_data(self, path): - if path in self.path_to_module: - return super().get_data(path) - elif path in self.path_to_bytecode: - name = self.path_to_bytecode[path] - return self.module_bytecode[name] - else: - raise IOError - - def is_package(self, name): - try: - return super().is_package(name) - except TypeError: - return '__init__' in self.bytecode_to_path[name] - - def get_code(self, name): - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - code_object = super().get_code(name) - assert len(w) == 1 - assert issubclass(w[0].category, DeprecationWarning) - return code_object - -class PyLoaderTests(testing_abc.LoaderTests): - - """Tests for importlib.abc.PyLoader.""" - - mocker = PyLoaderMock - - def eq_attrs(self, ob, **kwargs): - for attr, val in kwargs.items(): - found = getattr(ob, attr) - self.assertEqual(found, val, - "{} attribute: {} != {}".format(attr, found, val)) - - def test_module(self): - name = '' - path = os.path.join('', 'path', 'to', 'module') - mock = self.mocker({name: path}) - with util.uncache(name): - module = mock.load_module(name) - self.assertIn(name, sys.modules) - self.eq_attrs(module, __name__=name, __file__=path, __package__='', - __loader__=mock) - self.assertTrue(not hasattr(module, '__path__')) - return mock, name - - def test_package(self): - name = '' - path = os.path.join('path', 'to', name, '__init__') - mock = self.mocker({name: path}) - with util.uncache(name): - module = mock.load_module(name) - self.assertIn(name, sys.modules) - self.eq_attrs(module, __name__=name, __file__=path, - __path__=[os.path.dirname(path)], __package__=name, - __loader__=mock) - return mock, name - - def test_lacking_parent(self): - name = 'pkg.mod' - path = os.path.join('path', 'to', 'pkg', 'mod') - mock = self.mocker({name: path}) - with util.uncache(name): - module = mock.load_module(name) - self.assertIn(name, sys.modules) - self.eq_attrs(module, __name__=name, __file__=path, __package__='pkg', - __loader__=mock) - self.assertFalse(hasattr(module, '__path__')) - return mock, name - - def test_module_reuse(self): - name = 'mod' - path = os.path.join('path', 'to', 'mod') - module = imp.new_module(name) - mock = self.mocker({name: path}) - with util.uncache(name): - sys.modules[name] = module - loaded_module = mock.load_module(name) - self.assertIs(loaded_module, module) - self.assertIs(sys.modules[name], module) - return mock, name - - def test_state_after_failure(self): - name = "mod" - module = imp.new_module(name) - module.blah = None - mock = self.mocker({name: os.path.join('path', 'to', 'mod')}) - mock.source = b"1/0" - with util.uncache(name): - sys.modules[name] = module - with self.assertRaises(ZeroDivisionError): - mock.load_module(name) - self.assertIs(sys.modules[name], module) - self.assertTrue(hasattr(module, 'blah')) - return mock - - def test_unloadable(self): - name = "mod" - mock = self.mocker({name: os.path.join('path', 'to', 'mod')}) - mock.source = b"1/0" - with util.uncache(name): - with self.assertRaises(ZeroDivisionError): - mock.load_module(name) - self.assertNotIn(name, sys.modules) - return mock - - -class PyLoaderCompatTests(PyLoaderTests): - - """Test that the suggested code to make a loader that is compatible from - Python 3.1 forward works.""" - - mocker = PyLoaderCompatMock - - -class PyLoaderInterfaceTests(unittest.TestCase): - - """Tests for importlib.abc.PyLoader to make sure that when source_path() - doesn't return a path everything works as expected.""" - - def test_no_source_path(self): - # No source path should lead to ImportError. - name = 'mod' - mock = PyLoaderMock({}) - with util.uncache(name), self.assertRaises(ImportError): - mock.load_module(name) - - def test_source_path_is_None(self): - name = 'mod' - mock = PyLoaderMock({name: None}) - with util.uncache(name), self.assertRaises(ImportError): - mock.load_module(name) - - def test_get_filename_with_source_path(self): - # get_filename() should return what source_path() returns. - name = 'mod' - path = os.path.join('path', 'to', 'source') - mock = PyLoaderMock({name: path}) - with util.uncache(name): - self.assertEqual(mock.get_filename(name), path) - - def test_get_filename_no_source_path(self): - # get_filename() should raise ImportError if source_path returns None. - name = 'mod' - mock = PyLoaderMock({name: None}) - with util.uncache(name), self.assertRaises(ImportError): - mock.get_filename(name) - - -class PyPycLoaderTests(PyLoaderTests): - - """Tests for importlib.abc.PyPycLoader.""" - - mocker = PyPycLoaderMock - - @source_util.writes_bytecode_files - def verify_bytecode(self, mock, name): - assert name in mock.module_paths - self.assertIn(name, mock.module_bytecode) - magic = mock.module_bytecode[name][:4] - self.assertEqual(magic, imp.get_magic()) - mtime = importlib._r_long(mock.module_bytecode[name][4:8]) - self.assertEqual(mtime, 1) - source_size = mock.module_bytecode[name][8:12] - self.assertEqual(len(mock.source) & 0xFFFFFFFF, - importlib._r_long(source_size)) - bc = mock.module_bytecode[name][12:] - self.assertEqual(bc, mock.compile_bc(name)) - - def test_module(self): - mock, name = super().test_module() - self.verify_bytecode(mock, name) - - def test_package(self): - mock, name = super().test_package() - self.verify_bytecode(mock, name) - - def test_lacking_parent(self): - mock, name = super().test_lacking_parent() - self.verify_bytecode(mock, name) - - def test_module_reuse(self): - mock, name = super().test_module_reuse() - self.verify_bytecode(mock, name) - - def test_state_after_failure(self): - super().test_state_after_failure() - - def test_unloadable(self): - super().test_unloadable() - - -class PyPycLoaderInterfaceTests(unittest.TestCase): - - """Test for the interface of importlib.abc.PyPycLoader.""" - - def get_filename_check(self, src_path, bc_path, expect): - name = 'mod' - mock = PyPycLoaderMock({name: src_path}, {name: {'path': bc_path}}) - with util.uncache(name): - assert mock.source_path(name) == src_path - assert mock.bytecode_path(name) == bc_path - self.assertEqual(mock.get_filename(name), expect) - - def test_filename_with_source_bc(self): - # When source and bytecode paths present, return the source path. - self.get_filename_check('source_path', 'bc_path', 'source_path') - - def test_filename_with_source_no_bc(self): - # With source but no bc, return source path. - self.get_filename_check('source_path', None, 'source_path') - - def test_filename_with_no_source_bc(self): - # With not source but bc, return the bc path. - self.get_filename_check(None, 'bc_path', 'bc_path') - - def test_filename_with_no_source_or_bc(self): - # With no source or bc, raise ImportError. - name = 'mod' - mock = PyPycLoaderMock({name: None}, {name: {'path': None}}) - with util.uncache(name), self.assertRaises(ImportError): - mock.get_filename(name) - - -class SkipWritingBytecodeTests(unittest.TestCase): - - """Test that bytecode is properly handled based on - sys.dont_write_bytecode.""" - - @source_util.writes_bytecode_files - def run_test(self, dont_write_bytecode): - name = 'mod' - mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')}) - sys.dont_write_bytecode = dont_write_bytecode - with util.uncache(name): - mock.load_module(name) - self.assertIsNot(name in mock.module_bytecode, dont_write_bytecode) - - def test_no_bytecode_written(self): - self.run_test(True) - - def test_bytecode_written(self): - self.run_test(False) - - -class RegeneratedBytecodeTests(unittest.TestCase): - - """Test that bytecode is regenerated as expected.""" - - @source_util.writes_bytecode_files - def test_different_magic(self): - # A different magic number should lead to new bytecode. - name = 'mod' - bad_magic = b'\x00\x00\x00\x00' - assert bad_magic != imp.get_magic() - mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')}, - {name: {'path': os.path.join('path', 'to', - 'mod.bytecode'), - 'magic': bad_magic}}) - with util.uncache(name): - mock.load_module(name) - self.assertIn(name, mock.module_bytecode) - magic = mock.module_bytecode[name][:4] - self.assertEqual(magic, imp.get_magic()) - - @source_util.writes_bytecode_files - def test_old_mtime(self): - # Bytecode with an older mtime should be regenerated. - name = 'mod' - old_mtime = PyPycLoaderMock.default_mtime - 1 - mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')}, - {name: {'path': 'path/to/mod.bytecode', 'mtime': old_mtime}}) - with util.uncache(name): - mock.load_module(name) - self.assertIn(name, mock.module_bytecode) - mtime = importlib._r_long(mock.module_bytecode[name][4:8]) - self.assertEqual(mtime, PyPycLoaderMock.default_mtime) - - -class BadBytecodeFailureTests(unittest.TestCase): - - """Test import failures when there is no source and parts of the bytecode - is bad.""" - - def test_bad_magic(self): - # A bad magic number should lead to an ImportError. - name = 'mod' - bad_magic = b'\x00\x00\x00\x00' - bc = {name: - {'path': os.path.join('path', 'to', 'mod'), - 'magic': bad_magic}} - mock = PyPycLoaderMock({name: None}, bc) - with util.uncache(name), self.assertRaises(ImportError) as cm: - mock.load_module(name) - self.assertEqual(cm.exception.name, name) - - def test_no_bytecode(self): - # Missing code object bytecode should lead to an EOFError. - name = 'mod' - bc = {name: {'path': os.path.join('path', 'to', 'mod'), 'bc': b''}} - mock = PyPycLoaderMock({name: None}, bc) - with util.uncache(name), self.assertRaises(EOFError): - mock.load_module(name) - - def test_bad_bytecode(self): - # Malformed code object bytecode should lead to a ValueError. - name = 'mod' - bc = {name: {'path': os.path.join('path', 'to', 'mod'), 'bc': b'1234'}} - mock = PyPycLoaderMock({name: None}, bc) - with util.uncache(name), self.assertRaises(ValueError): - mock.load_module(name) - - def raise_ImportError(*args, **kwargs): raise ImportError -class MissingPathsTests(unittest.TestCase): - - """Test what happens when a source or bytecode path does not exist (either - from *_path returning None or raising ImportError).""" - - def test_source_path_None(self): - # Bytecode should be used when source_path returns None, along with - # __file__ being set to the bytecode path. - name = 'mod' - bytecode_path = 'path/to/mod' - mock = PyPycLoaderMock({name: None}, {name: {'path': bytecode_path}}) - with util.uncache(name): - module = mock.load_module(name) - self.assertEqual(module.__file__, bytecode_path) - - # Testing for bytecode_path returning None handled by all tests where no - # bytecode initially exists. - - def test_all_paths_None(self): - # If all *_path methods return None, raise ImportError. - name = 'mod' - mock = PyPycLoaderMock({name: None}) - with util.uncache(name), self.assertRaises(ImportError) as cm: - mock.load_module(name) - self.assertEqual(cm.exception.name, name) - - def test_source_path_ImportError(self): - # An ImportError from source_path should trigger an ImportError. - name = 'mod' - mock = PyPycLoaderMock({}, {name: {'path': os.path.join('path', 'to', - 'mod')}}) - with util.uncache(name), self.assertRaises(ImportError): - mock.load_module(name) - - def test_bytecode_path_ImportError(self): - # An ImportError from bytecode_path should trigger an ImportError. - name = 'mod' - mock = PyPycLoaderMock({name: os.path.join('path', 'to', 'mod')}) - bad_meth = types.MethodType(raise_ImportError, mock) - mock.bytecode_path = bad_meth - with util.uncache(name), self.assertRaises(ImportError) as cm: - mock.load_module(name) - class SourceLoaderTestHarness(unittest.TestCase): @@ -801,6 +327,7 @@ class Loader(abc.Loader): def load_module(self, fullname): super().load_module(fullname) + def module_repr(self, module): super().module_repr(module) @@ -825,20 +352,6 @@ class SourceLoader(ResourceLoader, ExecutionLoader, abc.SourceLoader): pass - class PyLoader(ResourceLoader, InspectLoader, abc.PyLoader): - def source_path(self, _): - super().source_path(_) - - class PyPycLoader(PyLoader, abc.PyPycLoader): - def bytecode_path(self, _): - super().bytecode_path(_) - - def source_mtime(self, _): - super().source_mtime(_) - - def write_bytecode(self, _, _2): - super().write_bytecode(_, _2) - def raises_NotImplementedError(self, ins, *args): for method_name in args: method = getattr(ins, method_name) @@ -877,24 +390,12 @@ # Required abstractmethods. self.raises_NotImplementedError(ins, 'get_filename', 'get_data') # Optional abstractmethods. - self.raises_NotImplementedError(ins,'path_stats', 'set_data') - - def test_PyLoader(self): - self.raises_NotImplementedError(self.PyLoader(), 'source_path', - 'get_data', 'is_package') - - def test_PyPycLoader(self): - self.raises_NotImplementedError(self.PyPycLoader(), 'source_path', - 'source_mtime', 'bytecode_path', - 'write_bytecode') + self.raises_NotImplementedError(ins, 'path_stats', 'set_data') def test_main(): from test.support import run_unittest - run_unittest(PyLoaderTests, PyLoaderCompatTests, - PyLoaderInterfaceTests, - PyPycLoaderTests, PyPycLoaderInterfaceTests, - SkipWritingBytecodeTests, RegeneratedBytecodeTests, + run_unittest(SkipWritingBytecodeTests, RegeneratedBytecodeTests, BadBytecodeFailureTests, MissingPathsTests, SourceOnlyLoaderTests, SourceLoaderBytecodeTests, diff --git a/Lib/test/test_importlib/test_abc.py b/Lib/test/test_importlib/test_abc.py --- a/Lib/test/test_importlib/test_abc.py +++ b/Lib/test/test_importlib/test_abc.py @@ -43,11 +43,6 @@ subclasses = [machinery.FileFinder] -class Loader(InheritanceTests, unittest.TestCase): - - subclasses = [abc.PyLoader] - - class ResourceLoader(InheritanceTests, unittest.TestCase): superclasses = [abc.Loader] @@ -56,14 +51,13 @@ class InspectLoader(InheritanceTests, unittest.TestCase): superclasses = [abc.Loader] - subclasses = [abc.PyLoader, machinery.BuiltinImporter, + subclasses = [machinery.BuiltinImporter, machinery.FrozenImporter, machinery.ExtensionFileLoader] class ExecutionLoader(InheritanceTests, unittest.TestCase): superclasses = [abc.InspectLoader] - subclasses = [abc.PyLoader] class FileLoader(InheritanceTests, unittest.TestCase): @@ -78,16 +72,6 @@ subclasses = [machinery.SourceFileLoader] -class PyLoader(InheritanceTests, unittest.TestCase): - - superclasses = [abc.Loader, abc.ResourceLoader, abc.ExecutionLoader] - - -class PyPycLoader(InheritanceTests, unittest.TestCase): - - superclasses = [abc.PyLoader] - - def test_main(): from test.support import run_unittest classes = [] diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -107,6 +107,9 @@ Library ------- +- Issue #15641: Clean up deprecated classes from importlib + Patch by Taras Lyapun. + - Issue #16350: zlib.Decompress.decompress() now accumulates data from successive calls after EOF in unused_data, instead of only saving the argument to the last call. Patch by Serhiy Storchaka. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 11:41:07 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 5 Nov 2012 11:41:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_The_migration_?= =?utf-8?q?to_importlib_eliminated_this_crasher?= Message-ID: <3Xw9R73HmMzRF1@mail.python.org> http://hg.python.org/cpython/rev/e29b50e1e8e5 changeset: 80266:e29b50e1e8e5 branch: 3.3 parent: 80261:367e376e5ba2 user: Nick Coghlan date: Mon Nov 05 20:40:25 2012 +1000 summary: The migration to importlib eliminated this crasher If anyone finds another recursive C path that bypasses the recursion limiting, they can add a new crasher example. files: Lib/test/crashers/recursion_limit_too_high.py | 16 ---------- 1 files changed, 0 insertions(+), 16 deletions(-) diff --git a/Lib/test/crashers/recursion_limit_too_high.py b/Lib/test/crashers/recursion_limit_too_high.py deleted file mode 100644 --- a/Lib/test/crashers/recursion_limit_too_high.py +++ /dev/null @@ -1,16 +0,0 @@ -# The following example may crash or not depending on the platform. -# E.g. on 32-bit Intel Linux in a "standard" configuration it seems to -# crash on Python 2.5 (but not 2.4 nor 2.3). On Windows the import -# eventually fails to find the module, possibly because we run out of -# file handles. - -# The point of this example is to show that sys.setrecursionlimit() is a -# hack, and not a robust solution. This example simply exercises a path -# where it takes many C-level recursions, consuming a lot of stack -# space, for each Python-level recursion. So 1000 times this amount of -# stack space may be too much for standard platforms already. - -import sys -if 'recursion_limit_too_high' in sys.modules: - del sys.modules['recursion_limit_too_high'] -import recursion_limit_too_high -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 11:41:08 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 5 Nov 2012 11:41:08 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_from_3=2E3?= Message-ID: <3Xw9R85wnvzRG4@mail.python.org> http://hg.python.org/cpython/rev/c4b5dfcb4a01 changeset: 80267:c4b5dfcb4a01 parent: 80265:48228fb874c1 parent: 80266:e29b50e1e8e5 user: Nick Coghlan date: Mon Nov 05 20:40:57 2012 +1000 summary: Merge from 3.3 files: Lib/test/crashers/recursion_limit_too_high.py | 16 ---------- 1 files changed, 0 insertions(+), 16 deletions(-) diff --git a/Lib/test/crashers/recursion_limit_too_high.py b/Lib/test/crashers/recursion_limit_too_high.py deleted file mode 100644 --- a/Lib/test/crashers/recursion_limit_too_high.py +++ /dev/null @@ -1,16 +0,0 @@ -# The following example may crash or not depending on the platform. -# E.g. on 32-bit Intel Linux in a "standard" configuration it seems to -# crash on Python 2.5 (but not 2.4 nor 2.3). On Windows the import -# eventually fails to find the module, possibly because we run out of -# file handles. - -# The point of this example is to show that sys.setrecursionlimit() is a -# hack, and not a robust solution. This example simply exercises a path -# where it takes many C-level recursions, consuming a lot of stack -# space, for each Python-level recursion. So 1000 times this amount of -# stack space may be too much for standard platforms already. - -import sys -if 'recursion_limit_too_high' in sys.modules: - del sys.modules['recursion_limit_too_high'] -import recursion_limit_too_high -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 12:33:35 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 5 Nov 2012 12:33:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E2=29=3A_Record_a_known?= =?utf-8?q?_crasher_from_=236717?= Message-ID: <3XwBbg69pqzRG2@mail.python.org> http://hg.python.org/cpython/rev/0dfa3b09a6fe changeset: 80268:0dfa3b09a6fe branch: 3.2 parent: 80255:be882735e0b6 user: Nick Coghlan date: Mon Nov 05 21:26:57 2012 +1000 summary: Record a known crasher from #6717 files: Lib/test/crashers/trace_at_recursion_limit.py | 27 ++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Lib/test/crashers/trace_at_recursion_limit.py b/Lib/test/crashers/trace_at_recursion_limit.py new file mode 100644 --- /dev/null +++ b/Lib/test/crashers/trace_at_recursion_limit.py @@ -0,0 +1,27 @@ +""" +From http://bugs.python.org/issue6717 + +A misbehaving trace hook can trigger a segfault by exceeding the recursion +limit. +""" +import sys + + +def x(): + pass + +def g(*args): + if True: # change to True to crash interpreter + try: + x() + except: + pass + return g + +def f(): + print(sys.getrecursionlimit()) + f() + +sys.settrace(g) + +f() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 12:33:37 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 5 Nov 2012 12:33:37 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_=236717_crasher_from_3=2E2?= Message-ID: <3XwBbj1ZxmzRHd@mail.python.org> http://hg.python.org/cpython/rev/509f7a53f8cc changeset: 80269:509f7a53f8cc branch: 3.3 parent: 80266:e29b50e1e8e5 parent: 80268:0dfa3b09a6fe user: Nick Coghlan date: Mon Nov 05 21:32:11 2012 +1000 summary: Merge #6717 crasher from 3.2 files: Lib/test/crashers/trace_at_recursion_limit.py | 27 ++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Lib/test/crashers/trace_at_recursion_limit.py b/Lib/test/crashers/trace_at_recursion_limit.py new file mode 100644 --- /dev/null +++ b/Lib/test/crashers/trace_at_recursion_limit.py @@ -0,0 +1,27 @@ +""" +From http://bugs.python.org/issue6717 + +A misbehaving trace hook can trigger a segfault by exceeding the recursion +limit. +""" +import sys + + +def x(): + pass + +def g(*args): + if True: # change to True to crash interpreter + try: + x() + except: + pass + return g + +def f(): + print(sys.getrecursionlimit()) + f() + +sys.settrace(g) + +f() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 12:33:38 2012 From: python-checkins at python.org (nick.coghlan) Date: Mon, 5 Nov 2012 12:33:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_=236717_crasher_from_3=2E3?= Message-ID: <3XwBbk41YmzRJb@mail.python.org> http://hg.python.org/cpython/rev/47943fe516ec changeset: 80270:47943fe516ec parent: 80267:c4b5dfcb4a01 parent: 80269:509f7a53f8cc user: Nick Coghlan date: Mon Nov 05 21:33:22 2012 +1000 summary: Merge #6717 crasher from 3.3 files: Lib/test/crashers/trace_at_recursion_limit.py | 27 ++++++++++ 1 files changed, 27 insertions(+), 0 deletions(-) diff --git a/Lib/test/crashers/trace_at_recursion_limit.py b/Lib/test/crashers/trace_at_recursion_limit.py new file mode 100644 --- /dev/null +++ b/Lib/test/crashers/trace_at_recursion_limit.py @@ -0,0 +1,27 @@ +""" +From http://bugs.python.org/issue6717 + +A misbehaving trace hook can trigger a segfault by exceeding the recursion +limit. +""" +import sys + + +def x(): + pass + +def g(*args): + if True: # change to True to crash interpreter + try: + x() + except: + pass + return g + +def f(): + print(sys.getrecursionlimit()) + f() + +sys.settrace(g) + +f() -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 21:23:27 2012 From: python-checkins at python.org (ezio.melotti) Date: Mon, 5 Nov 2012 21:23:27 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Fix_typo_notic?= =?utf-8?q?ed_by_Tom_Lynn=2E?= Message-ID: <3XwQM36CJPzRFd@mail.python.org> http://hg.python.org/cpython/rev/e99e7e2f61d2 changeset: 80271:e99e7e2f61d2 branch: 3.3 parent: 80269:509f7a53f8cc user: Ezio Melotti date: Mon Nov 05 22:22:48 2012 +0200 summary: Fix typo noticed by Tom Lynn. files: Doc/library/time.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -309,7 +309,7 @@ On Windows versions older than Vista, :func:`monotonic` detects :c:func:`GetTickCount` integer overflow (32 bits, roll-over after 49.7 days). - It increases an internal epoch (reference time by) 2\ :sup:`32` each time + It increases an internal epoch (reference time) by 2\ :sup:`32` each time that an overflow is detected. The epoch is stored in the process-local state and so the value of :func:`monotonic` may be different in two Python processes running for more than 49 days. On more recent versions of Windows -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Mon Nov 5 21:23:29 2012 From: python-checkins at python.org (ezio.melotti) Date: Mon, 5 Nov 2012 21:23:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_typo_fix=2E?= Message-ID: <3XwQM51lwWzRGZ@mail.python.org> http://hg.python.org/cpython/rev/ec00f8570c55 changeset: 80272:ec00f8570c55 parent: 80270:47943fe516ec parent: 80271:e99e7e2f61d2 user: Ezio Melotti date: Mon Nov 05 22:23:16 2012 +0200 summary: Merge typo fix. files: Doc/library/time.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -309,7 +309,7 @@ On Windows versions older than Vista, :func:`monotonic` detects :c:func:`GetTickCount` integer overflow (32 bits, roll-over after 49.7 days). - It increases an internal epoch (reference time by) 2\ :sup:`32` each time + It increases an internal epoch (reference time) by 2\ :sup:`32` each time that an overflow is detected. The epoch is stored in the process-local state and so the value of :func:`monotonic` may be different in two Python processes running for more than 49 days. On more recent versions of Windows -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Tue Nov 6 05:55:19 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Tue, 06 Nov 2012 05:55:19 +0100 Subject: [Python-checkins] Daily reference leaks (ec00f8570c55): sum=0 Message-ID: results for ec00f8570c55 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogYLPyMK', '-x'] From python-checkins at python.org Tue Nov 6 14:56:02 2012 From: python-checkins at python.org (tim.golden) Date: Tue, 6 Nov 2012 14:56:02 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_issue9584=3A_Add_=7B=7D_li?= =?utf-8?q?st_expansion_to_glob=2E_Original_patch_by_Mathieu_Bridon?= Message-ID: <3XwsjZ4sTWzLs9@mail.python.org> http://hg.python.org/cpython/rev/dafca4714298 changeset: 80273:dafca4714298 user: Tim Golden date: Tue Nov 06 13:50:42 2012 +0000 summary: issue9584: Add {} list expansion to glob. Original patch by Mathieu Bridon files: Doc/library/glob.rst | 11 ++-- Lib/glob.py | 65 ++++++++++++++++++++++-------- Lib/test/test_glob.py | 64 +++++++++++++++++++++++++++++- Misc/NEWS | 3 + 4 files changed, 118 insertions(+), 25 deletions(-) diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -13,10 +13,10 @@ The :mod:`glob` module finds all the pathnames matching a specified pattern according to the rules used by the Unix shell. No tilde expansion is done, but -``*``, ``?``, and character ranges expressed with ``[]`` will be correctly -matched. This is done by using the :func:`os.listdir` and -:func:`fnmatch.fnmatch` functions in concert, and not by actually invoking a -subshell. (For tilde and shell variable expansion, use +``*``, ``?``, character ranges expressed with ``[]`` and list of options +expressed with ``{}`` will be correctly matched. This is done by using the +:func:`os.listdir` and :func:`fnmatch.fnmatch` functions in concert, and not by +actually invoking a subshell. (For tilde and shell variable expansion, use :func:`os.path.expanduser` and :func:`os.path.expandvars`.) @@ -47,7 +47,8 @@ ['1.gif', 'card.gif'] >>> glob.glob('?.gif') ['1.gif'] - + >>> glob.glob('?.{gif,txt}') + ['1.gif', '2.txt'] .. seealso:: diff --git a/Lib/glob.py b/Lib/glob.py --- a/Lib/glob.py +++ b/Lib/glob.py @@ -14,6 +14,7 @@ """ return list(iglob(pathname)) + def iglob(pathname): """Return an iterator which yields the paths matching a pathname pattern. @@ -24,21 +25,24 @@ if os.path.lexists(pathname): yield pathname return - dirname, basename = os.path.split(pathname) - if not dirname: - yield from glob1(None, basename) - return - if has_magic(dirname): - dirs = iglob(dirname) - else: - dirs = [dirname] - if has_magic(basename): - glob_in_dir = glob1 - else: - glob_in_dir = glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename): - yield os.path.join(dirname, name) + pathnames = expand_braces(pathname) + for pathname in pathnames: + dirname, basename = os.path.split(pathname) + if not dirname: + yield from glob1(None, basename) + return + + if has_magic(dirname): + dirs = iglob(dirname) + else: + dirs = [dirname] + if has_magic(basename): + glob_in_dir = glob1 + else: + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) # These 2 helper functions non-recursively glob inside a literal directory. # They return a list of basenames. `glob1` accepts a pattern while `glob0` @@ -70,12 +74,37 @@ return [] -magic_check = re.compile('[*?[]') -magic_check_bytes = re.compile(b'[*?[]') - +magic_check = re.compile('[*?[{]') +magic_check_bytes = re.compile(b'[*?[{]') def has_magic(s): if isinstance(s, bytes): match = magic_check_bytes.search(s) else: match = magic_check.search(s) return match is not None + +brace_matcher = re.compile(r'.*(\{.+?[^\\]\})') +def expand_braces(text): + """Find the rightmost, innermost set of braces and, if it contains a + comma-separated list, expand its contents recursively (any of its items + may itself be a list enclosed in braces). + + Return the full set of expanded strings. + """ + res = set() + + match = brace_matcher.search(text) + if match is not None: + sub = match.group(1) + open_brace, close_brace = match.span(1) + if "," in sub: + for pat in sub.strip('{}').split(','): + res.update(expand_braces(text[:open_brace] + pat + text[close_brace:])) + + else: + res.update(expand_braces(text[:open_brace] + sub.replace('}', '\\}') + text[close_brace:])) + + else: + res.add(text.replace('\\}', '}')) + + return res diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -5,7 +5,7 @@ import os import shutil -class GlobTests(unittest.TestCase): +class GlobTestsBase(unittest.TestCase): def norm(self, *parts): return os.path.normpath(os.path.join(self.tempdir, *parts)) @@ -45,6 +45,8 @@ def assertSequencesEqual_noorder(self, l1, l2): self.assertEqual(set(l1), set(l2)) +class GlobTests(GlobTestsBase): + def test_glob_literal(self): eq = self.assertSequencesEqual_noorder eq(self.glob('a'), [self.norm('a')]) @@ -105,9 +107,67 @@ eq(self.glob('sym1'), [self.norm('sym1')]) eq(self.glob('sym2'), [self.norm('sym2')]) +class GlobBracesTests(GlobTestsBase): + + def setUp(self): + super(GlobBracesTests, self).setUp() + self.mktemp('c{}d') + self.mktemp('c{deg') + self.mktemp('c{dfg') + self.mktemp('cd{f}g') + self.mktemp('ce{f}g') + self.mktemp('cdf}g') + self.mktemp('cef}g') + + def match_pattern_with_results(self, patterns, paths): + expected = [self.norm(path) for path in [os.path.join(*parts) for parts in paths]] + actual = [os.path.normpath(g) for g in self.glob(*patterns)] + self.assertSequencesEqual_noorder(actual, expected) + + def test_two_terms(self): + self.match_pattern_with_results(['a{aa,ab}'], [["aaa"], ["aab"]]) + + def test_missing_first_plus_nested(self): + self.match_pattern_with_results(['a{,a{a,b}}'], [['a'], ['aaa'], ['aab']]) + + def test_one_subpath_with_two_file_terms(self): + self.match_pattern_with_results(['a', '{D,bcd}'], [['a', 'D'], ['a', 'bcd']]) + + def test_two_subpath_terms_with_two_file_terms(self): + self.match_pattern_with_results(['{aaa,aab}', '{F,zzzF}'], [('aaa', 'zzzF'), ('aab', 'F')]) + + def test_two_subpath_terms_with_wildcard_file_term(self): + self.match_pattern_with_results(['aa{a,b}', '*F'], [('aaa', 'zzzF'), ('aab', 'F')]) + + def test_wildcard_subpath_with_file_missing_first_term(self): + self.match_pattern_with_results(['aa?', '{,zzz}F'], [('aaa', 'zzzF'), ('aab', 'F')]) + + # + # Edge cases where braces should not be expanded + # + def test_empty_braces(self): + self.assertSequencesEqual_noorder(self.glob('c{}d'), [self.norm('c{}d')]) + + def test_missing_end_brace(self): + self.assertSequencesEqual_noorder(self.glob('c{d{e,f}g'), map(self.norm, ['c{deg', 'c{dfg'])) + + def test_second_brace_one_term(self): + self.assertSequencesEqual_noorder(self.glob('c{d,e}{f}g'), map(self.norm, ['cd{f}g', 'ce{f}g'])) + + def test_outer_term_missing_first_brace(self): + self.assertSequencesEqual_noorder(self.glob('c{d,e}f}g'), map(self.norm, ['cdf}g', 'cef}g'])) + + # + # Braces containing folder separators + # + def test_embedded_separator1(self): + self.match_pattern_with_results(['a/{D,bcd/{EF,efg}}'], [('a', 'D'), ('a', 'bcd', 'EF'), ('a', 'bcd', 'efg')]) + + def test_embedded_separator2(self): + self.match_pattern_with_results(['aa{a/zzz,b/}F'], [('aaa', 'zzzF'), ('aab', 'F')]) def test_main(): - run_unittest(GlobTests) + run_unittest(GlobTests, GlobBracesTests) if __name__ == "__main__": diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #9584: glob.glob now expands braces to a list of strings. + Original patch by Mathieu Bridon. + - Issue #8271: the utf-8 decoder now outputs the correct number of U+FFFD characters when used with the 'replace' error handler on invalid utf-8 sequences. Patch by Serhiy Storchaka, tests by Ezio Melotti. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 14:56:03 2012 From: python-checkins at python.org (tim.golden) Date: Tue, 6 Nov 2012 14:56:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Correct_mis-indented_white?= =?utf-8?q?space?= Message-ID: <3Xwsjc00B0zNQP@mail.python.org> http://hg.python.org/cpython/rev/5cf6c427fd39 changeset: 80274:5cf6c427fd39 user: Tim Golden date: Tue Nov 06 13:55:42 2012 +0000 summary: Correct mis-indented whitespace files: Lib/glob.py | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Lib/glob.py b/Lib/glob.py --- a/Lib/glob.py +++ b/Lib/glob.py @@ -27,22 +27,22 @@ return pathnames = expand_braces(pathname) for pathname in pathnames: - dirname, basename = os.path.split(pathname) - if not dirname: - yield from glob1(None, basename) - return + dirname, basename = os.path.split(pathname) + if not dirname: + yield from glob1(None, basename) + return - if has_magic(dirname): - dirs = iglob(dirname) - else: - dirs = [dirname] - if has_magic(basename): - glob_in_dir = glob1 - else: - glob_in_dir = glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename): - yield os.path.join(dirname, name) + if has_magic(dirname): + dirs = iglob(dirname) + else: + dirs = [dirname] + if has_magic(basename): + glob_in_dir = glob1 + else: + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) # These 2 helper functions non-recursively glob inside a literal directory. # They return a list of basenames. `glob1` accepts a pattern while `glob0` -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 16:24:16 2012 From: python-checkins at python.org (marc-andre.lemburg) Date: Tue, 6 Nov 2012 16:24:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Clarify_the_meaning_of_=22num?= =?utf-8?q?ber_of_affected_rows=22_in_the_DB-API_2=2E0?= Message-ID: <3XwvgN6c7QzLqN@mail.python.org> http://hg.python.org/peps/rev/888c87639210 changeset: 4577:888c87639210 user: Marc-Andre Lemburg date: Tue Nov 06 16:24:07 2012 +0100 summary: Clarify the meaning of "number of affected rows" in the DB-API 2.0 as discussed on the db-sig list. files: pep-0249.txt | 20 +++----------------- 1 files changed, 3 insertions(+), 17 deletions(-) diff --git a/pep-0249.txt b/pep-0249.txt --- a/pep-0249.txt +++ b/pep-0249.txt @@ -1,7 +1,7 @@ PEP: 249 Title: Python Database API Specification v2.0 -Version: $Revision$ -Last-Modified: $Date$ +Version: $Revision: 56119 $ +Last-Modified: $Date: 2007-06-28 22:11:32 +0200 (Thu, 28 Jun 2007) $ Author: mal at lemburg.com (Marc-Andr? Lemburg) Discussions-To: db-sig at python.org Status: Final @@ -287,7 +287,7 @@ This read-only attribute specifies the number of rows that the last .execute*() produced (for DQL statements like 'select') or affected (for DML statements like 'update' or - 'insert'). [9] + 'insert'). The attribute is -1 in case no .execute*() has been performed on the cursor or the rowcount of the last @@ -1127,20 +1127,6 @@ implement the tp_iter slot on the cursor object instead of the .__iter__() method. - [9] The term "number of affected rows" generally refers to the - number of rows deleted, updated or inserted by the last - statement run on the database cursor. Most databases will - return the total number of rows that were found by the - corresponding WHERE clause of the statement. Some databases - use a different interpretation for UPDATEs and only return the - number of rows that were changed by the UPDATE, even though - the WHERE clause of the statement may have found more matching - rows. Database module authors should try to implement the more - common interpretation of returning the total number of rows - found by the WHERE clause, or clearly document a different - interpretation of the rowcount attribute. - - Acknowledgements Many thanks go to Andrew Kuchling who converted the Python -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Tue Nov 6 16:38:23 2012 From: python-checkins at python.org (tim.golden) Date: Tue, 6 Nov 2012 16:38:23 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Backed_out_changeset_5cf6c?= =?utf-8?q?427fd39?= Message-ID: <3Xwvzg03bZzLvs@mail.python.org> http://hg.python.org/cpython/rev/7065056aa30e changeset: 80275:7065056aa30e user: Tim Golden date: Tue Nov 06 15:32:50 2012 +0000 summary: Backed out changeset 5cf6c427fd39 files: Lib/glob.py | 30 +++++++++++++++--------------- 1 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Lib/glob.py b/Lib/glob.py --- a/Lib/glob.py +++ b/Lib/glob.py @@ -27,22 +27,22 @@ return pathnames = expand_braces(pathname) for pathname in pathnames: - dirname, basename = os.path.split(pathname) - if not dirname: - yield from glob1(None, basename) - return + dirname, basename = os.path.split(pathname) + if not dirname: + yield from glob1(None, basename) + return - if has_magic(dirname): - dirs = iglob(dirname) - else: - dirs = [dirname] - if has_magic(basename): - glob_in_dir = glob1 - else: - glob_in_dir = glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename): - yield os.path.join(dirname, name) + if has_magic(dirname): + dirs = iglob(dirname) + else: + dirs = [dirname] + if has_magic(basename): + glob_in_dir = glob1 + else: + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) # These 2 helper functions non-recursively glob inside a literal directory. # They return a list of basenames. `glob1` accepts a pattern while `glob0` -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 16:38:24 2012 From: python-checkins at python.org (tim.golden) Date: Tue, 6 Nov 2012 16:38:24 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Backed_out_changeset_dafca?= =?utf-8?q?4714298?= Message-ID: <3Xwvzh3hDbzMQy@mail.python.org> http://hg.python.org/cpython/rev/a29f15f743a2 changeset: 80276:a29f15f743a2 parent: 80273:dafca4714298 user: Tim Golden date: Tue Nov 06 15:33:30 2012 +0000 summary: Backed out changeset dafca4714298 files: Doc/library/glob.rst | 11 ++-- Lib/glob.py | 65 ++++++++---------------------- Lib/test/test_glob.py | 64 +----------------------------- Misc/NEWS | 3 - 4 files changed, 25 insertions(+), 118 deletions(-) diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -13,10 +13,10 @@ The :mod:`glob` module finds all the pathnames matching a specified pattern according to the rules used by the Unix shell. No tilde expansion is done, but -``*``, ``?``, character ranges expressed with ``[]`` and list of options -expressed with ``{}`` will be correctly matched. This is done by using the -:func:`os.listdir` and :func:`fnmatch.fnmatch` functions in concert, and not by -actually invoking a subshell. (For tilde and shell variable expansion, use +``*``, ``?``, and character ranges expressed with ``[]`` will be correctly +matched. This is done by using the :func:`os.listdir` and +:func:`fnmatch.fnmatch` functions in concert, and not by actually invoking a +subshell. (For tilde and shell variable expansion, use :func:`os.path.expanduser` and :func:`os.path.expandvars`.) @@ -47,8 +47,7 @@ ['1.gif', 'card.gif'] >>> glob.glob('?.gif') ['1.gif'] - >>> glob.glob('?.{gif,txt}') - ['1.gif', '2.txt'] + .. seealso:: diff --git a/Lib/glob.py b/Lib/glob.py --- a/Lib/glob.py +++ b/Lib/glob.py @@ -14,7 +14,6 @@ """ return list(iglob(pathname)) - def iglob(pathname): """Return an iterator which yields the paths matching a pathname pattern. @@ -25,24 +24,21 @@ if os.path.lexists(pathname): yield pathname return - pathnames = expand_braces(pathname) - for pathname in pathnames: - dirname, basename = os.path.split(pathname) - if not dirname: - yield from glob1(None, basename) - return - - if has_magic(dirname): - dirs = iglob(dirname) - else: - dirs = [dirname] - if has_magic(basename): - glob_in_dir = glob1 - else: - glob_in_dir = glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename): - yield os.path.join(dirname, name) + dirname, basename = os.path.split(pathname) + if not dirname: + yield from glob1(None, basename) + return + if has_magic(dirname): + dirs = iglob(dirname) + else: + dirs = [dirname] + if has_magic(basename): + glob_in_dir = glob1 + else: + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) # These 2 helper functions non-recursively glob inside a literal directory. # They return a list of basenames. `glob1` accepts a pattern while `glob0` @@ -74,37 +70,12 @@ return [] -magic_check = re.compile('[*?[{]') -magic_check_bytes = re.compile(b'[*?[{]') +magic_check = re.compile('[*?[]') +magic_check_bytes = re.compile(b'[*?[]') + def has_magic(s): if isinstance(s, bytes): match = magic_check_bytes.search(s) else: match = magic_check.search(s) return match is not None - -brace_matcher = re.compile(r'.*(\{.+?[^\\]\})') -def expand_braces(text): - """Find the rightmost, innermost set of braces and, if it contains a - comma-separated list, expand its contents recursively (any of its items - may itself be a list enclosed in braces). - - Return the full set of expanded strings. - """ - res = set() - - match = brace_matcher.search(text) - if match is not None: - sub = match.group(1) - open_brace, close_brace = match.span(1) - if "," in sub: - for pat in sub.strip('{}').split(','): - res.update(expand_braces(text[:open_brace] + pat + text[close_brace:])) - - else: - res.update(expand_braces(text[:open_brace] + sub.replace('}', '\\}') + text[close_brace:])) - - else: - res.add(text.replace('\\}', '}')) - - return res diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -5,7 +5,7 @@ import os import shutil -class GlobTestsBase(unittest.TestCase): +class GlobTests(unittest.TestCase): def norm(self, *parts): return os.path.normpath(os.path.join(self.tempdir, *parts)) @@ -45,8 +45,6 @@ def assertSequencesEqual_noorder(self, l1, l2): self.assertEqual(set(l1), set(l2)) -class GlobTests(GlobTestsBase): - def test_glob_literal(self): eq = self.assertSequencesEqual_noorder eq(self.glob('a'), [self.norm('a')]) @@ -107,67 +105,9 @@ eq(self.glob('sym1'), [self.norm('sym1')]) eq(self.glob('sym2'), [self.norm('sym2')]) -class GlobBracesTests(GlobTestsBase): - - def setUp(self): - super(GlobBracesTests, self).setUp() - self.mktemp('c{}d') - self.mktemp('c{deg') - self.mktemp('c{dfg') - self.mktemp('cd{f}g') - self.mktemp('ce{f}g') - self.mktemp('cdf}g') - self.mktemp('cef}g') - - def match_pattern_with_results(self, patterns, paths): - expected = [self.norm(path) for path in [os.path.join(*parts) for parts in paths]] - actual = [os.path.normpath(g) for g in self.glob(*patterns)] - self.assertSequencesEqual_noorder(actual, expected) - - def test_two_terms(self): - self.match_pattern_with_results(['a{aa,ab}'], [["aaa"], ["aab"]]) - - def test_missing_first_plus_nested(self): - self.match_pattern_with_results(['a{,a{a,b}}'], [['a'], ['aaa'], ['aab']]) - - def test_one_subpath_with_two_file_terms(self): - self.match_pattern_with_results(['a', '{D,bcd}'], [['a', 'D'], ['a', 'bcd']]) - - def test_two_subpath_terms_with_two_file_terms(self): - self.match_pattern_with_results(['{aaa,aab}', '{F,zzzF}'], [('aaa', 'zzzF'), ('aab', 'F')]) - - def test_two_subpath_terms_with_wildcard_file_term(self): - self.match_pattern_with_results(['aa{a,b}', '*F'], [('aaa', 'zzzF'), ('aab', 'F')]) - - def test_wildcard_subpath_with_file_missing_first_term(self): - self.match_pattern_with_results(['aa?', '{,zzz}F'], [('aaa', 'zzzF'), ('aab', 'F')]) - - # - # Edge cases where braces should not be expanded - # - def test_empty_braces(self): - self.assertSequencesEqual_noorder(self.glob('c{}d'), [self.norm('c{}d')]) - - def test_missing_end_brace(self): - self.assertSequencesEqual_noorder(self.glob('c{d{e,f}g'), map(self.norm, ['c{deg', 'c{dfg'])) - - def test_second_brace_one_term(self): - self.assertSequencesEqual_noorder(self.glob('c{d,e}{f}g'), map(self.norm, ['cd{f}g', 'ce{f}g'])) - - def test_outer_term_missing_first_brace(self): - self.assertSequencesEqual_noorder(self.glob('c{d,e}f}g'), map(self.norm, ['cdf}g', 'cef}g'])) - - # - # Braces containing folder separators - # - def test_embedded_separator1(self): - self.match_pattern_with_results(['a/{D,bcd/{EF,efg}}'], [('a', 'D'), ('a', 'bcd', 'EF'), ('a', 'bcd', 'efg')]) - - def test_embedded_separator2(self): - self.match_pattern_with_results(['aa{a/zzz,b/}F'], [('aaa', 'zzzF'), ('aab', 'F')]) def test_main(): - run_unittest(GlobTests, GlobBracesTests) + run_unittest(GlobTests) if __name__ == "__main__": diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,9 +10,6 @@ Core and Builtins ----------------- -- Issue #9584: glob.glob now expands braces to a list of strings. - Original patch by Mathieu Bridon. - - Issue #8271: the utf-8 decoder now outputs the correct number of U+FFFD characters when used with the 'replace' error handler on invalid utf-8 sequences. Patch by Serhiy Storchaka, tests by Ezio Melotti. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 16:38:26 2012 From: python-checkins at python.org (tim.golden) Date: Tue, 6 Nov 2012 16:38:26 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?q?=29=3A_Reversed_changes_from_issue9584?= Message-ID: <3Xwvzk05kdzM34@mail.python.org> http://hg.python.org/cpython/rev/ec897bb38708 changeset: 80277:ec897bb38708 parent: 80275:7065056aa30e parent: 80276:a29f15f743a2 user: Tim Golden date: Tue Nov 06 15:34:23 2012 +0000 summary: Reversed changes from issue9584 files: Doc/library/glob.rst | 11 ++-- Lib/glob.py | 65 ++++++++---------------------- Lib/test/test_glob.py | 64 +----------------------------- Misc/NEWS | 3 - 4 files changed, 25 insertions(+), 118 deletions(-) diff --git a/Doc/library/glob.rst b/Doc/library/glob.rst --- a/Doc/library/glob.rst +++ b/Doc/library/glob.rst @@ -13,10 +13,10 @@ The :mod:`glob` module finds all the pathnames matching a specified pattern according to the rules used by the Unix shell. No tilde expansion is done, but -``*``, ``?``, character ranges expressed with ``[]`` and list of options -expressed with ``{}`` will be correctly matched. This is done by using the -:func:`os.listdir` and :func:`fnmatch.fnmatch` functions in concert, and not by -actually invoking a subshell. (For tilde and shell variable expansion, use +``*``, ``?``, and character ranges expressed with ``[]`` will be correctly +matched. This is done by using the :func:`os.listdir` and +:func:`fnmatch.fnmatch` functions in concert, and not by actually invoking a +subshell. (For tilde and shell variable expansion, use :func:`os.path.expanduser` and :func:`os.path.expandvars`.) @@ -47,8 +47,7 @@ ['1.gif', 'card.gif'] >>> glob.glob('?.gif') ['1.gif'] - >>> glob.glob('?.{gif,txt}') - ['1.gif', '2.txt'] + .. seealso:: diff --git a/Lib/glob.py b/Lib/glob.py --- a/Lib/glob.py +++ b/Lib/glob.py @@ -14,7 +14,6 @@ """ return list(iglob(pathname)) - def iglob(pathname): """Return an iterator which yields the paths matching a pathname pattern. @@ -25,24 +24,21 @@ if os.path.lexists(pathname): yield pathname return - pathnames = expand_braces(pathname) - for pathname in pathnames: - dirname, basename = os.path.split(pathname) - if not dirname: - yield from glob1(None, basename) - return - - if has_magic(dirname): - dirs = iglob(dirname) - else: - dirs = [dirname] - if has_magic(basename): - glob_in_dir = glob1 - else: - glob_in_dir = glob0 - for dirname in dirs: - for name in glob_in_dir(dirname, basename): - yield os.path.join(dirname, name) + dirname, basename = os.path.split(pathname) + if not dirname: + yield from glob1(None, basename) + return + if has_magic(dirname): + dirs = iglob(dirname) + else: + dirs = [dirname] + if has_magic(basename): + glob_in_dir = glob1 + else: + glob_in_dir = glob0 + for dirname in dirs: + for name in glob_in_dir(dirname, basename): + yield os.path.join(dirname, name) # These 2 helper functions non-recursively glob inside a literal directory. # They return a list of basenames. `glob1` accepts a pattern while `glob0` @@ -74,37 +70,12 @@ return [] -magic_check = re.compile('[*?[{]') -magic_check_bytes = re.compile(b'[*?[{]') +magic_check = re.compile('[*?[]') +magic_check_bytes = re.compile(b'[*?[]') + def has_magic(s): if isinstance(s, bytes): match = magic_check_bytes.search(s) else: match = magic_check.search(s) return match is not None - -brace_matcher = re.compile(r'.*(\{.+?[^\\]\})') -def expand_braces(text): - """Find the rightmost, innermost set of braces and, if it contains a - comma-separated list, expand its contents recursively (any of its items - may itself be a list enclosed in braces). - - Return the full set of expanded strings. - """ - res = set() - - match = brace_matcher.search(text) - if match is not None: - sub = match.group(1) - open_brace, close_brace = match.span(1) - if "," in sub: - for pat in sub.strip('{}').split(','): - res.update(expand_braces(text[:open_brace] + pat + text[close_brace:])) - - else: - res.update(expand_braces(text[:open_brace] + sub.replace('}', '\\}') + text[close_brace:])) - - else: - res.add(text.replace('\\}', '}')) - - return res diff --git a/Lib/test/test_glob.py b/Lib/test/test_glob.py --- a/Lib/test/test_glob.py +++ b/Lib/test/test_glob.py @@ -5,7 +5,7 @@ import os import shutil -class GlobTestsBase(unittest.TestCase): +class GlobTests(unittest.TestCase): def norm(self, *parts): return os.path.normpath(os.path.join(self.tempdir, *parts)) @@ -45,8 +45,6 @@ def assertSequencesEqual_noorder(self, l1, l2): self.assertEqual(set(l1), set(l2)) -class GlobTests(GlobTestsBase): - def test_glob_literal(self): eq = self.assertSequencesEqual_noorder eq(self.glob('a'), [self.norm('a')]) @@ -107,67 +105,9 @@ eq(self.glob('sym1'), [self.norm('sym1')]) eq(self.glob('sym2'), [self.norm('sym2')]) -class GlobBracesTests(GlobTestsBase): - - def setUp(self): - super(GlobBracesTests, self).setUp() - self.mktemp('c{}d') - self.mktemp('c{deg') - self.mktemp('c{dfg') - self.mktemp('cd{f}g') - self.mktemp('ce{f}g') - self.mktemp('cdf}g') - self.mktemp('cef}g') - - def match_pattern_with_results(self, patterns, paths): - expected = [self.norm(path) for path in [os.path.join(*parts) for parts in paths]] - actual = [os.path.normpath(g) for g in self.glob(*patterns)] - self.assertSequencesEqual_noorder(actual, expected) - - def test_two_terms(self): - self.match_pattern_with_results(['a{aa,ab}'], [["aaa"], ["aab"]]) - - def test_missing_first_plus_nested(self): - self.match_pattern_with_results(['a{,a{a,b}}'], [['a'], ['aaa'], ['aab']]) - - def test_one_subpath_with_two_file_terms(self): - self.match_pattern_with_results(['a', '{D,bcd}'], [['a', 'D'], ['a', 'bcd']]) - - def test_two_subpath_terms_with_two_file_terms(self): - self.match_pattern_with_results(['{aaa,aab}', '{F,zzzF}'], [('aaa', 'zzzF'), ('aab', 'F')]) - - def test_two_subpath_terms_with_wildcard_file_term(self): - self.match_pattern_with_results(['aa{a,b}', '*F'], [('aaa', 'zzzF'), ('aab', 'F')]) - - def test_wildcard_subpath_with_file_missing_first_term(self): - self.match_pattern_with_results(['aa?', '{,zzz}F'], [('aaa', 'zzzF'), ('aab', 'F')]) - - # - # Edge cases where braces should not be expanded - # - def test_empty_braces(self): - self.assertSequencesEqual_noorder(self.glob('c{}d'), [self.norm('c{}d')]) - - def test_missing_end_brace(self): - self.assertSequencesEqual_noorder(self.glob('c{d{e,f}g'), map(self.norm, ['c{deg', 'c{dfg'])) - - def test_second_brace_one_term(self): - self.assertSequencesEqual_noorder(self.glob('c{d,e}{f}g'), map(self.norm, ['cd{f}g', 'ce{f}g'])) - - def test_outer_term_missing_first_brace(self): - self.assertSequencesEqual_noorder(self.glob('c{d,e}f}g'), map(self.norm, ['cdf}g', 'cef}g'])) - - # - # Braces containing folder separators - # - def test_embedded_separator1(self): - self.match_pattern_with_results(['a/{D,bcd/{EF,efg}}'], [('a', 'D'), ('a', 'bcd', 'EF'), ('a', 'bcd', 'efg')]) - - def test_embedded_separator2(self): - self.match_pattern_with_results(['aa{a/zzz,b/}F'], [('aaa', 'zzzF'), ('aab', 'F')]) def test_main(): - run_unittest(GlobTests, GlobBracesTests) + run_unittest(GlobTests) if __name__ == "__main__": diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,9 +10,6 @@ Core and Builtins ----------------- -- Issue #9584: glob.glob now expands braces to a list of strings. - Original patch by Mathieu Bridon. - - Issue #8271: the utf-8 decoder now outputs the correct number of U+FFFD characters when used with the 'replace' error handler on invalid utf-8 sequences. Patch by Serhiy Storchaka, tests by Ezio Melotti. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 23:23:28 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 6 Nov 2012 23:23:28 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316414=3A_Add_supp?= =?utf-8?q?ort=2EFS=5FNONASCII_and_support=2ETESTFN=5FNONASCII?= Message-ID: <3Xx4z42lcszMGY@mail.python.org> http://hg.python.org/cpython/rev/de8cf1ece068 changeset: 80278:de8cf1ece068 user: Victor Stinner date: Tue Nov 06 23:23:43 2012 +0100 summary: Issue #16414: Add support.FS_NONASCII and support.TESTFN_NONASCII These constants are used to test functions with non-ASCII data, especially filenames. files: Lib/test/support.py | 31 ++++++++++++++++++++ Lib/test/test_cmd_line.py | 6 +- Lib/test/test_cmd_line_script.py | 11 +----- Lib/test/test_genericpath.py | 2 + Lib/test/test_os.py | 4 ++ 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -603,6 +603,32 @@ # module name. TESTFN = "{}_{}_tmp".format(TESTFN, os.getpid()) +# FS_NONASCII: non-ASCII character encodable by os.fsencode(), +# or None if there is no such character. +FS_NONASCII = None +for character in ( + # U+00E6 (Latin small letter AE): Encodable to cp1252, cp1254, cp1257, iso-8859-1 + '\u00E6', + # U+0141 (Latin capital letter L with stroke): Encodable to cp1250, cp1257 + '\u0141', + # U+041A (Cyrillic capital letter KA): Encodable to cp932, cp950, cp1251 + '\u041A', + # U+05D0 (Hebrew Letter Alef): Encodable to cp424, cp1255 + '\u05D0', + # U+06A9 (Arabic letter KEHEH): Encodable to cp1256 + '\u06A9', + # U+03A9 (Greek capital letter OMEGA): Encodable to cp932, cp950, cp1253 + '\u03A9', + # U+0E01 (Thai character KO KAI): Encodable to cp874 + '\u0E01', +): + try: + os.fsdecode(os.fsencode(character)) + except UnicodeError: + pass + else: + FS_NONASCII = character + break # TESTFN_UNICODE is a non-ascii filename TESTFN_UNICODE = TESTFN + "-\xe0\xf2\u0258\u0141\u011f" @@ -658,6 +684,11 @@ TESTFN_UNDECODABLE = name break +if FS_NONASCII: + TESTFN_NONASCII = TESTFN + '- ' + FS_NONASCII +else: + TESTFN_NONASCII = None + # Save the initial cwd SAVEDCWD = os.getcwd() diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -93,15 +93,15 @@ # All good if execution is successful assert_python_ok('-c', 'pass') - @unittest.skipIf(sys.getfilesystemencoding() == 'ascii', - 'need a filesystem encoding different than ASCII') + @unittest.skipUnless(test.support.FS_NONASCII, 'need support.FS_NONASCII') def test_non_ascii(self): # Test handling of non-ascii data if test.support.verbose: import locale print('locale encoding = %s, filesystem encoding = %s' % (locale.getpreferredencoding(), sys.getfilesystemencoding())) - command = "assert(ord('\xe9') == 0xe9)" + command = ("assert(ord(%r) == %s)" + % (test.support.FS_NONASCII, ord(test.support.FS_NONASCII))) assert_python_ok('-c', command) # On Windows, pass bytes to subprocess doesn't test how Python decodes the diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -363,19 +363,12 @@ self.assertTrue(text[1].startswith(' File ')) self.assertTrue(text[3].startswith('NameError')) + @unittest.skipUnless(support.TESTFN_NONASCII, 'need support.TESTFN_NONASCII') def test_non_ascii(self): # Issue #16218 # non-ascii filename encodable to cp1252, cp932, latin1 and utf8 - filename = support.TESTFN + '\xa3' - try: - os.fsencode(filename) - except UnicodeEncodeError: - self.skipTest( - "Filesystem encoding %r cannot encode " - "the filename: %a" - % (sys.getfilesystemencoding(), filename)) source = 'print(ascii(__file__))\n' - script_name = _make_test_script(os.curdir, filename, source) + script_name = _make_test_script(os.curdir, support.TESTFN_NONASCII, source) self.addCleanup(support.unlink, script_name) rc, stdout, stderr = assert_python_ok(script_name) self.assertEqual( diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -313,6 +313,8 @@ def test_nonascii_abspath(self): if support.TESTFN_UNDECODABLE: name = support.TESTFN_UNDECODABLE + elif support.TESTFN_NONASCII: + name = support.TESTFN_NONASCII else: name = b'a\xffb\xe7w\xf0' diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1243,6 +1243,8 @@ def setUp(self): if support.TESTFN_UNENCODABLE: self.dir = support.TESTFN_UNENCODABLE + elif support.TESTFN_NONASCII: + self.dir = support.TESTFN_NONASCII else: self.dir = support.TESTFN self.bdir = os.fsencode(self.dir) @@ -1257,6 +1259,8 @@ add_filename(support.TESTFN_UNICODE) if support.TESTFN_UNENCODABLE: add_filename(support.TESTFN_UNENCODABLE) + if support.TESTFN_NONASCII: + add_filename(support.TESTFN_NONASCII) if not bytesfn: self.skipTest("couldn't create any non-ascii filename") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 23:33:32 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 6 Nov 2012 23:33:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316414=3A_Fix_supp?= =?utf-8?q?ort=2ETESTFN=5FUNDECODABLE_and?= Message-ID: <3Xx5Bh70Z4zMH5@mail.python.org> http://hg.python.org/cpython/rev/0e9fbdda3c92 changeset: 80279:0e9fbdda3c92 user: Victor Stinner date: Tue Nov 06 23:33:46 2012 +0100 summary: Issue #16414: Fix support.TESTFN_UNDECODABLE and test_genericpath.test_nonascii_abspath() * support.TESTFN_UNDECODABLE was decodable if the filesystem encoding was cp932 * test_genericpath.test_nonascii_abspath() didn't work on Windows if the path was not decodable (ex: with cp932) files: Lib/test/support.py | 6 ++++- Lib/test/test_genericpath.py | 27 ++++++++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -677,7 +677,11 @@ # decoded from the filesystem encoding (in strict mode). It can be None if we # cannot generate such filename. TESTFN_UNDECODABLE = None -for name in (b'abc\xff', b'\xe7w\xf0'): +# b'\xff' is not decodable by os.fsdecode() with code page 932. Windows +# accepts it to create a file or a directory, or don't accept to enter to +# such directory (when the bytes name is used). So test b'\xe7' first: it is +# not decodable from cp932. +for name in (b'\xe7w\xf0', b'abc\xff'): try: os.fsdecode(name) except UnicodeDecodeError: diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -308,17 +308,28 @@ for path in ('', 'fuu', 'f\xf9\xf9', '/fuu', 'U:\\'): self.assertIsInstance(abspath(path), str) - @unittest.skipIf(sys.platform == 'darwin', - "Mac OS X denies the creation of a directory with an invalid utf8 name") def test_nonascii_abspath(self): - if support.TESTFN_UNDECODABLE: - name = support.TESTFN_UNDECODABLE - elif support.TESTFN_NONASCII: - name = support.TESTFN_NONASCII + # Test non-ASCII in the path + if sys.platform in ('win32', 'darwin'): + if support.TESTFN_NONASCII: + name = support.TESTFN_NONASCII + else: + # Mac OS X denies the creation of a directory with an invalid + # UTF-8 name. Windows allows to create a directory with an + # arbitrary bytes name, but fails to enter this directory + # (when the bytes name is used). + self.skipTest("need support.TESTFN_NONASCII") else: - name = b'a\xffb\xe7w\xf0' + if support.TESTFN_UNDECODABLE: + name = support.TESTFN_UNDECODABLE + elif support.TESTFN_NONASCII: + name = support.TESTFN_NONASCII + else: + # On UNIX, the surrogateescape error handler is used to + # decode paths, so any byte is allowed, it does not depend + # on the locale + name = b'a\xffb\xe7w\xf0' - # Test non-ASCII, non-UTF8 bytes in the path. with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) with support.temp_cwd(name): -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 23:40:07 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 6 Nov 2012 23:40:07 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316414=3A_Fix_typo?= =?utf-8?q?_in_support=2ETESTFN=5FNONASCII_=28useless_space=29?= Message-ID: <3Xx5LH6DlVzMG3@mail.python.org> http://hg.python.org/cpython/rev/55710b8c6670 changeset: 80280:55710b8c6670 user: Victor Stinner date: Tue Nov 06 23:40:22 2012 +0100 summary: Issue #16414: Fix typo in support.TESTFN_NONASCII (useless space) files: Lib/test/support.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -689,7 +689,7 @@ break if FS_NONASCII: - TESTFN_NONASCII = TESTFN + '- ' + FS_NONASCII + TESTFN_NONASCII = TESTFN + '-' + FS_NONASCII else: TESTFN_NONASCII = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 23:43:06 2012 From: python-checkins at python.org (victor.stinner) Date: Tue, 6 Nov 2012 23:43:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316414=3A_Test_mor?= =?utf-8?q?e_characters_for_support=2EFS=5FNONASCII?= Message-ID: <3Xx5Pk28w9zMG3@mail.python.org> http://hg.python.org/cpython/rev/7f90305d9f23 changeset: 80281:7f90305d9f23 user: Victor Stinner date: Tue Nov 06 23:43:21 2012 +0100 summary: Issue #16414: Test more characters for support.FS_NONASCII It should increase the probability of finding a non-ASCII character on any locale encoding. files: Lib/test/support.py | 35 ++++++++++++++++++++++++-------- 1 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -607,20 +607,37 @@ # or None if there is no such character. FS_NONASCII = None for character in ( - # U+00E6 (Latin small letter AE): Encodable to cp1252, cp1254, cp1257, iso-8859-1 + # First try printable and common characters to have a readable filename. + # For each character, the encoding list are just example of encodings able + # to encode the character (the list is not exhaustive). + + # U+00E6 (Latin Small Letter Ae): cp1252, iso-8859-1 '\u00E6', - # U+0141 (Latin capital letter L with stroke): Encodable to cp1250, cp1257 + # U+0130 (Latin Capital Letter I With Dot Above): cp1254, iso8859_3 + '\u0130', + # U+0141 (Latin Capital Letter L With Stroke): cp1250, cp1257 '\u0141', - # U+041A (Cyrillic capital letter KA): Encodable to cp932, cp950, cp1251 + # U+03C6 (Greek Small Letter Phi): cp1253 + '\u03C6', + # U+041A (Cyrillic Capital Letter Ka): cp1251 '\u041A', - # U+05D0 (Hebrew Letter Alef): Encodable to cp424, cp1255 + # U+05D0 (Hebrew Letter Alef): Encodable to cp424 '\u05D0', - # U+06A9 (Arabic letter KEHEH): Encodable to cp1256 - '\u06A9', - # U+03A9 (Greek capital letter OMEGA): Encodable to cp932, cp950, cp1253 - '\u03A9', - # U+0E01 (Thai character KO KAI): Encodable to cp874 + # U+060C (Arabic Comma): cp864, cp1006, iso8859_6, mac_arabic + '\u060C', + # U+062A (Arabic Letter Teh): cp720 + '\u062A', + # U+0E01 (Thai Character Ko Kai): cp874 '\u0E01', + + # Then try more "special" characters. "special" because they may be + # interpreted or displayed differently depending on the exact locale + # encoding and the font. + + # U+00A0 (No-Break Space) + '\u00A0', + # U+20AC (Euro Sign) + '\u20AC', ): try: os.fsdecode(os.fsencode(character)) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 23:56:36 2012 From: python-checkins at python.org (stefan.krah) Date: Tue, 6 Nov 2012 23:56:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=283=2E3=29=3A_Backport_fc8f1?= =?utf-8?q?b1c76bf=2E?= Message-ID: <3Xx5jJ4jzVzMH5@mail.python.org> http://hg.python.org/cpython/rev/55cc29d7e83a changeset: 80282:55cc29d7e83a branch: 3.3 parent: 80271:e99e7e2f61d2 user: Stefan Krah date: Tue Nov 06 23:27:24 2012 +0100 summary: Backport fc8f1b1c76bf. files: Lib/test/test_buffer.py | 20 +++++--------------- 1 files changed, 5 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_buffer.py b/Lib/test/test_buffer.py --- a/Lib/test/test_buffer.py +++ b/Lib/test/test_buffer.py @@ -4001,23 +4001,13 @@ # equality-hash invariant x = ndarray(list(range(12)), shape=[12], format='B') - a = memoryview(nd) + a = memoryview(x) y = ndarray(list(range(12)), shape=[12], format='b') - b = memoryview(nd) - - z = ndarray(list(bytes(chr(x), 'latin-1') for x in range(12)), - shape=[12], format='c') - c = memoryview(nd) - - if (a == b): - self.assertEqual(hash(a), hash(b)) - - if (a == c): - self.assertEqual(hash(a), hash(c)) - - if (b == c): - self.assertEqual(hash(b), hash(c)) + b = memoryview(y) + + self.assertEqual(a, b) + self.assertEqual(hash(a), hash(b)) # non-byte formats nd = ndarray(list(range(12)), shape=[2,2,3], format='L') -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 23:56:38 2012 From: python-checkins at python.org (stefan.krah) Date: Tue, 6 Nov 2012 23:56:38 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Null_merge=2E?= Message-ID: <3Xx5jL0CJBzMWH@mail.python.org> http://hg.python.org/cpython/rev/4059b7a551df changeset: 80283:4059b7a551df parent: 80277:ec897bb38708 parent: 80282:55cc29d7e83a user: Stefan Krah date: Tue Nov 06 23:36:08 2012 +0100 summary: Null merge. files: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 23:56:39 2012 From: python-checkins at python.org (stefan.krah) Date: Tue, 6 Nov 2012 23:56:39 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2Uu?= Message-ID: <3Xx5jM3x21zMch@mail.python.org> http://hg.python.org/cpython/rev/80f51c128d08 changeset: 80284:80f51c128d08 parent: 80283:4059b7a551df parent: 80279:0e9fbdda3c92 user: Stefan Krah date: Tue Nov 06 23:51:42 2012 +0100 summary: Merge. files: Lib/test/support.py | 37 +++++++++++++++++++- Lib/test/test_cmd_line.py | 6 +- Lib/test/test_cmd_line_script.py | 11 +---- Lib/test/test_genericpath.py | 25 ++++++++++--- Lib/test/test_os.py | 4 ++ 5 files changed, 64 insertions(+), 19 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -603,6 +603,32 @@ # module name. TESTFN = "{}_{}_tmp".format(TESTFN, os.getpid()) +# FS_NONASCII: non-ASCII character encodable by os.fsencode(), +# or None if there is no such character. +FS_NONASCII = None +for character in ( + # U+00E6 (Latin small letter AE): Encodable to cp1252, cp1254, cp1257, iso-8859-1 + '\u00E6', + # U+0141 (Latin capital letter L with stroke): Encodable to cp1250, cp1257 + '\u0141', + # U+041A (Cyrillic capital letter KA): Encodable to cp932, cp950, cp1251 + '\u041A', + # U+05D0 (Hebrew Letter Alef): Encodable to cp424, cp1255 + '\u05D0', + # U+06A9 (Arabic letter KEHEH): Encodable to cp1256 + '\u06A9', + # U+03A9 (Greek capital letter OMEGA): Encodable to cp932, cp950, cp1253 + '\u03A9', + # U+0E01 (Thai character KO KAI): Encodable to cp874 + '\u0E01', +): + try: + os.fsdecode(os.fsencode(character)) + except UnicodeError: + pass + else: + FS_NONASCII = character + break # TESTFN_UNICODE is a non-ascii filename TESTFN_UNICODE = TESTFN + "-\xe0\xf2\u0258\u0141\u011f" @@ -651,13 +677,22 @@ # decoded from the filesystem encoding (in strict mode). It can be None if we # cannot generate such filename. TESTFN_UNDECODABLE = None -for name in (b'abc\xff', b'\xe7w\xf0'): +# b'\xff' is not decodable by os.fsdecode() with code page 932. Windows +# accepts it to create a file or a directory, or don't accept to enter to +# such directory (when the bytes name is used). So test b'\xe7' first: it is +# not decodable from cp932. +for name in (b'\xe7w\xf0', b'abc\xff'): try: os.fsdecode(name) except UnicodeDecodeError: TESTFN_UNDECODABLE = name break +if FS_NONASCII: + TESTFN_NONASCII = TESTFN + '- ' + FS_NONASCII +else: + TESTFN_NONASCII = None + # Save the initial cwd SAVEDCWD = os.getcwd() diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -93,15 +93,15 @@ # All good if execution is successful assert_python_ok('-c', 'pass') - @unittest.skipIf(sys.getfilesystemencoding() == 'ascii', - 'need a filesystem encoding different than ASCII') + @unittest.skipUnless(test.support.FS_NONASCII, 'need support.FS_NONASCII') def test_non_ascii(self): # Test handling of non-ascii data if test.support.verbose: import locale print('locale encoding = %s, filesystem encoding = %s' % (locale.getpreferredencoding(), sys.getfilesystemencoding())) - command = "assert(ord('\xe9') == 0xe9)" + command = ("assert(ord(%r) == %s)" + % (test.support.FS_NONASCII, ord(test.support.FS_NONASCII))) assert_python_ok('-c', command) # On Windows, pass bytes to subprocess doesn't test how Python decodes the diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -363,19 +363,12 @@ self.assertTrue(text[1].startswith(' File ')) self.assertTrue(text[3].startswith('NameError')) + @unittest.skipUnless(support.TESTFN_NONASCII, 'need support.TESTFN_NONASCII') def test_non_ascii(self): # Issue #16218 # non-ascii filename encodable to cp1252, cp932, latin1 and utf8 - filename = support.TESTFN + '\xa3' - try: - os.fsencode(filename) - except UnicodeEncodeError: - self.skipTest( - "Filesystem encoding %r cannot encode " - "the filename: %a" - % (sys.getfilesystemencoding(), filename)) source = 'print(ascii(__file__))\n' - script_name = _make_test_script(os.curdir, filename, source) + script_name = _make_test_script(os.curdir, support.TESTFN_NONASCII, source) self.addCleanup(support.unlink, script_name) rc, stdout, stderr = assert_python_ok(script_name) self.assertEqual( diff --git a/Lib/test/test_genericpath.py b/Lib/test/test_genericpath.py --- a/Lib/test/test_genericpath.py +++ b/Lib/test/test_genericpath.py @@ -308,15 +308,28 @@ for path in ('', 'fuu', 'f\xf9\xf9', '/fuu', 'U:\\'): self.assertIsInstance(abspath(path), str) - @unittest.skipIf(sys.platform == 'darwin', - "Mac OS X denies the creation of a directory with an invalid utf8 name") def test_nonascii_abspath(self): - if support.TESTFN_UNDECODABLE: - name = support.TESTFN_UNDECODABLE + # Test non-ASCII in the path + if sys.platform in ('win32', 'darwin'): + if support.TESTFN_NONASCII: + name = support.TESTFN_NONASCII + else: + # Mac OS X denies the creation of a directory with an invalid + # UTF-8 name. Windows allows to create a directory with an + # arbitrary bytes name, but fails to enter this directory + # (when the bytes name is used). + self.skipTest("need support.TESTFN_NONASCII") else: - name = b'a\xffb\xe7w\xf0' + if support.TESTFN_UNDECODABLE: + name = support.TESTFN_UNDECODABLE + elif support.TESTFN_NONASCII: + name = support.TESTFN_NONASCII + else: + # On UNIX, the surrogateescape error handler is used to + # decode paths, so any byte is allowed, it does not depend + # on the locale + name = b'a\xffb\xe7w\xf0' - # Test non-ASCII, non-UTF8 bytes in the path. with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) with support.temp_cwd(name): diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -1243,6 +1243,8 @@ def setUp(self): if support.TESTFN_UNENCODABLE: self.dir = support.TESTFN_UNENCODABLE + elif support.TESTFN_NONASCII: + self.dir = support.TESTFN_NONASCII else: self.dir = support.TESTFN self.bdir = os.fsencode(self.dir) @@ -1257,6 +1259,8 @@ add_filename(support.TESTFN_UNICODE) if support.TESTFN_UNENCODABLE: add_filename(support.TESTFN_UNENCODABLE) + if support.TESTFN_NONASCII: + add_filename(support.TESTFN_NONASCII) if not bytesfn: self.skipTest("couldn't create any non-ascii filename") -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Tue Nov 6 23:56:40 2012 From: python-checkins at python.org (stefan.krah) Date: Tue, 6 Nov 2012 23:56:40 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_default_-=3E_default?= =?utf-8?b?KTogTWVyZ2Uu?= Message-ID: <3Xx5jN6TFxzMcT@mail.python.org> http://hg.python.org/cpython/rev/55e58e2bf95c changeset: 80285:55e58e2bf95c parent: 80284:80f51c128d08 parent: 80281:7f90305d9f23 user: Stefan Krah date: Tue Nov 06 23:55:58 2012 +0100 summary: Merge. files: Lib/test/support.py | 37 ++++++++++++++++++++++++-------- 1 files changed, 27 insertions(+), 10 deletions(-) diff --git a/Lib/test/support.py b/Lib/test/support.py --- a/Lib/test/support.py +++ b/Lib/test/support.py @@ -607,20 +607,37 @@ # or None if there is no such character. FS_NONASCII = None for character in ( - # U+00E6 (Latin small letter AE): Encodable to cp1252, cp1254, cp1257, iso-8859-1 + # First try printable and common characters to have a readable filename. + # For each character, the encoding list are just example of encodings able + # to encode the character (the list is not exhaustive). + + # U+00E6 (Latin Small Letter Ae): cp1252, iso-8859-1 '\u00E6', - # U+0141 (Latin capital letter L with stroke): Encodable to cp1250, cp1257 + # U+0130 (Latin Capital Letter I With Dot Above): cp1254, iso8859_3 + '\u0130', + # U+0141 (Latin Capital Letter L With Stroke): cp1250, cp1257 '\u0141', - # U+041A (Cyrillic capital letter KA): Encodable to cp932, cp950, cp1251 + # U+03C6 (Greek Small Letter Phi): cp1253 + '\u03C6', + # U+041A (Cyrillic Capital Letter Ka): cp1251 '\u041A', - # U+05D0 (Hebrew Letter Alef): Encodable to cp424, cp1255 + # U+05D0 (Hebrew Letter Alef): Encodable to cp424 '\u05D0', - # U+06A9 (Arabic letter KEHEH): Encodable to cp1256 - '\u06A9', - # U+03A9 (Greek capital letter OMEGA): Encodable to cp932, cp950, cp1253 - '\u03A9', - # U+0E01 (Thai character KO KAI): Encodable to cp874 + # U+060C (Arabic Comma): cp864, cp1006, iso8859_6, mac_arabic + '\u060C', + # U+062A (Arabic Letter Teh): cp720 + '\u062A', + # U+0E01 (Thai Character Ko Kai): cp874 '\u0E01', + + # Then try more "special" characters. "special" because they may be + # interpreted or displayed differently depending on the exact locale + # encoding and the font. + + # U+00A0 (No-Break Space) + '\u00A0', + # U+20AC (Euro Sign) + '\u20AC', ): try: os.fsdecode(os.fsencode(character)) @@ -689,7 +706,7 @@ break if FS_NONASCII: - TESTFN_NONASCII = TESTFN + '- ' + FS_NONASCII + TESTFN_NONASCII = TESTFN + '-' + FS_NONASCII else: TESTFN_NONASCII = None -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 00:10:14 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 7 Nov 2012 00:10:14 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Issue_=2316414=3A_Fix_test?= =?utf-8?q?=5Fos_on_Windows=2C_don=27t_test_os=2Elistdir=28=29_with_undeco?= =?utf-8?q?dable?= Message-ID: <3Xx6123yQgzM4D@mail.python.org> http://hg.python.org/cpython/rev/fce9e892c65d changeset: 80286:fce9e892c65d user: Victor Stinner date: Wed Nov 07 00:10:14 2012 +0100 summary: Issue #16414: Fix test_os on Windows, don't test os.listdir() with undecodable With the ANSI code page 932, os.listdir(b'\xe7') return an empty list (instead of failing), whereas os.listdir(b'\xff') raises a FileNotFoundError. It looks like a Windows bug: b'\xe7' directory does not exist, FindFirstFileA(b'\xe7') fails with ERROR_FILE_NOT_FOUND (2), instead of ERROR_PATH_NOT_FOUND (3). files: Lib/test/test_os.py | 12 +++++++++++- 1 files changed, 11 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -2076,7 +2076,6 @@ funcs = [ (self.filenames, os.chdir,), (self.filenames, os.chmod, 0o777), - (self.filenames, os.listdir,), (self.filenames, os.lstat,), (self.filenames, os.open, os.O_RDONLY), (self.filenames, os.rmdir,), @@ -2089,9 +2088,20 @@ (self.bytes_filenames, os.replace, b"dst"), (self.unicode_filenames, os.rename, "dst"), (self.unicode_filenames, os.replace, "dst"), + # Issue #16414: Don't test undecodable names with listdir() + # because of a Windows bug. + # + # With the ANSI code page 932, os.listdir(b'\xe7') return an + # empty list (instead of failing), whereas os.listdir(b'\xff') + # raises a FileNotFoundError. It looks like a Windows bug: + # b'\xe7' directory does not exist, FindFirstFileA(b'\xe7') + # fails with ERROR_FILE_NOT_FOUND (2), instead of + # ERROR_PATH_NOT_FOUND (3). + (self.unicode_filenames, os.listdir,), )) else: funcs.extend(( + (self.filenames, os.listdir,), (self.filenames, os.rename, "dst"), (self.filenames, os.replace, "dst"), )) -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 00:41:03 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 7 Nov 2012 00:41:03 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Close_=2316311=3A_Use_the_?= =?utf-8?q?=5FPyUnicodeWriter_API_in_text_decoders?= Message-ID: <3Xx6hb4dKyzMP7@mail.python.org> http://hg.python.org/cpython/rev/7ed9993d53b4 changeset: 80287:7ed9993d53b4 user: Victor Stinner date: Wed Nov 07 00:36:38 2012 +0100 summary: Close #16311: Use the _PyUnicodeWriter API in text decoders * Remove unicode_widen(): replaced with _PyUnicodeWriter_Prepare() * Remove unicode_putchar(): replaced with PyUnicodeWriter_Prepare() + PyUnicode_WRITER() * When handling an decoding error, only overallocate the buffer by +25% instead of +100% files: Objects/unicodeobject.c | 680 ++++++++++++++------------- 1 files changed, 342 insertions(+), 338 deletions(-) diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c --- a/Objects/unicodeobject.c +++ b/Objects/unicodeobject.c @@ -1644,38 +1644,6 @@ return unicode_resize(p_unicode, length); } -static int -unicode_widen(PyObject **p_unicode, Py_ssize_t length, - unsigned int maxchar) -{ - PyObject *result; - assert(PyUnicode_IS_READY(*p_unicode)); - assert(length <= PyUnicode_GET_LENGTH(*p_unicode)); - if (maxchar <= PyUnicode_MAX_CHAR_VALUE(*p_unicode)) - return 0; - result = PyUnicode_New(PyUnicode_GET_LENGTH(*p_unicode), - maxchar); - if (result == NULL) - return -1; - _PyUnicode_FastCopyCharacters(result, 0, *p_unicode, 0, length); - Py_DECREF(*p_unicode); - *p_unicode = result; - return 0; -} - -static int -unicode_putchar(PyObject **p_unicode, Py_ssize_t *pos, - Py_UCS4 ch) -{ - assert(ch <= MAX_UNICODE); - if (unicode_widen(p_unicode, *pos, ch) < 0) - return -1; - PyUnicode_WRITE(PyUnicode_KIND(*p_unicode), - PyUnicode_DATA(*p_unicode), - (*pos)++, ch); - return 0; -} - /* Copy a ASCII or latin1 char* string into a Python Unicode string. WARNING: The function doesn't copy the terminating null character and @@ -3925,6 +3893,7 @@ *exceptionObject = NULL; } +#ifdef HAVE_MBCS /* error handling callback helper: build arguments, call the callback and check the arguments, if no exception occurred, copy the replacement to the output @@ -3933,11 +3902,12 @@ */ static int -unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler, - const char *encoding, const char *reason, - const char **input, const char **inend, Py_ssize_t *startinpos, - Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, - PyObject **output, Py_ssize_t *outpos) +unicode_decode_call_errorhandler_wchar( + const char *errors, PyObject **errorHandler, + const char *encoding, const char *reason, + const char **input, const char **inend, Py_ssize_t *startinpos, + Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, + PyObject **output, Py_ssize_t *outpos) { static char *argparse = "O!n;decoding error handler must return (str, int) tuple"; @@ -3948,12 +3918,11 @@ Py_ssize_t requiredsize; Py_ssize_t newpos; PyObject *inputobj = NULL; - int res = -1; - - if (_PyUnicode_KIND(*output) != PyUnicode_WCHAR_KIND) - outsize = PyUnicode_GET_LENGTH(*output); - else - outsize = _PyUnicode_WSTR_LENGTH(*output); + wchar_t *repwstr; + Py_ssize_t repwlen; + + assert (_PyUnicode_KIND(*output) == PyUnicode_WCHAR_KIND); + outsize = _PyUnicode_WSTR_LENGTH(*output); if (*errorHandler == NULL) { *errorHandler = PyCodec_LookupError(errors); @@ -3978,8 +3947,6 @@ } if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos)) goto onError; - if (PyUnicode_READY(repunicode) == -1) - goto onError; /* Copy back the bytes variables, which might have been modified by the callback */ @@ -4003,54 +3970,112 @@ goto onError; } - if (_PyUnicode_KIND(*output) != PyUnicode_WCHAR_KIND) { - /* need more space? (at least enough for what we - have+the replacement+the rest of the string (starting - at the new input position), so we won't have to check space - when there are no errors in the rest of the string) */ - Py_ssize_t replen = PyUnicode_GET_LENGTH(repunicode); - requiredsize = *outpos + replen + insize-newpos; - if (requiredsize > outsize) { - if (requiredsize<2*outsize) - requiredsize = 2*outsize; - if (unicode_resize(output, requiredsize) < 0) - goto onError; - } - if (unicode_widen(output, *outpos, - PyUnicode_MAX_CHAR_VALUE(repunicode)) < 0) + repwstr = PyUnicode_AsUnicodeAndSize(repunicode, &repwlen); + if (repwstr == NULL) + goto onError; + /* need more space? (at least enough for what we + have+the replacement+the rest of the string (starting + at the new input position), so we won't have to check space + when there are no errors in the rest of the string) */ + requiredsize = *outpos + repwlen + insize-newpos; + if (requiredsize > outsize) { + if (requiredsize < 2*outsize) + requiredsize = 2*outsize; + if (unicode_resize(output, requiredsize) < 0) goto onError; - _PyUnicode_FastCopyCharacters(*output, *outpos, repunicode, 0, replen); - *outpos += replen; - } - else { - wchar_t *repwstr; - Py_ssize_t repwlen; - repwstr = PyUnicode_AsUnicodeAndSize(repunicode, &repwlen); - if (repwstr == NULL) - goto onError; - /* need more space? (at least enough for what we - have+the replacement+the rest of the string (starting - at the new input position), so we won't have to check space - when there are no errors in the rest of the string) */ - requiredsize = *outpos + repwlen + insize-newpos; - if (requiredsize > outsize) { - if (requiredsize < 2*outsize) - requiredsize = 2*outsize; - if (unicode_resize(output, requiredsize) < 0) - goto onError; - } - wcsncpy(_PyUnicode_WSTR(*output) + *outpos, repwstr, repwlen); - *outpos += repwlen; - } + } + wcsncpy(_PyUnicode_WSTR(*output) + *outpos, repwstr, repwlen); + *outpos += repwlen; + *endinpos = newpos; *inptr = *input + newpos; /* we made it! */ - res = 0; + Py_XDECREF(restuple); + return 0; onError: Py_XDECREF(restuple); - return res; + return -1; +} +#endif /* HAVE_MBCS */ + +static int +unicode_decode_call_errorhandler_writer( + const char *errors, PyObject **errorHandler, + const char *encoding, const char *reason, + const char **input, const char **inend, Py_ssize_t *startinpos, + Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, + _PyUnicodeWriter *writer /* PyObject **output, Py_ssize_t *outpos */) +{ + static char *argparse = "O!n;decoding error handler must return (str, int) tuple"; + + PyObject *restuple = NULL; + PyObject *repunicode = NULL; + Py_ssize_t insize; + Py_ssize_t newpos; + PyObject *inputobj = NULL; + + if (*errorHandler == NULL) { + *errorHandler = PyCodec_LookupError(errors); + if (*errorHandler == NULL) + goto onError; + } + + make_decode_exception(exceptionObject, + encoding, + *input, *inend - *input, + *startinpos, *endinpos, + reason); + if (*exceptionObject == NULL) + goto onError; + + restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL); + if (restuple == NULL) + goto onError; + if (!PyTuple_Check(restuple)) { + PyErr_SetString(PyExc_TypeError, &argparse[4]); + goto onError; + } + if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos)) + goto onError; + + /* Copy back the bytes variables, which might have been modified by the + callback */ + inputobj = PyUnicodeDecodeError_GetObject(*exceptionObject); + if (!inputobj) + goto onError; + if (!PyBytes_Check(inputobj)) { + PyErr_Format(PyExc_TypeError, "exception attribute object must be bytes"); + } + *input = PyBytes_AS_STRING(inputobj); + insize = PyBytes_GET_SIZE(inputobj); + *inend = *input + insize; + /* we can DECREF safely, as the exception has another reference, + so the object won't go away. */ + Py_DECREF(inputobj); + + if (newpos<0) + newpos = insize+newpos; + if (newpos<0 || newpos>insize) { + PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", newpos); + goto onError; + } + + writer->overallocate = 1; + if (_PyUnicodeWriter_WriteStr(writer, repunicode) == -1) + return + + *endinpos = newpos; + *inptr = *input + newpos; + + /* we made it! */ + Py_XDECREF(restuple); + return 0; + + onError: + Py_XDECREF(restuple); + return -1; } /* --- UTF-7 Codec -------------------------------------------------------- */ @@ -4158,9 +4183,8 @@ const char *starts = s; Py_ssize_t startinpos; Py_ssize_t endinpos; - Py_ssize_t outpos; const char *e; - PyObject *unicode; + _PyUnicodeWriter writer; const char *errmsg = ""; int inShift = 0; Py_ssize_t shiftOutStart; @@ -4170,17 +4194,19 @@ PyObject *errorHandler = NULL; PyObject *exc = NULL; - /* Start off assuming it's all ASCII. Widen later as necessary. */ - unicode = PyUnicode_New(size, 127); - if (!unicode) - return NULL; if (size == 0) { if (consumed) *consumed = 0; - return unicode; - } - - shiftOutStart = outpos = 0; + Py_INCREF(unicode_empty); + return unicode_empty; + } + + /* Start off assuming it's all ASCII. Widen later as necessary. */ + _PyUnicodeWriter_Init(&writer, 0); + if (_PyUnicodeWriter_Prepare(&writer, size, 127) == -1) + goto onError; + + shiftOutStart = 0; e = s + size; while (s < e) { @@ -4202,14 +4228,18 @@ /* expecting a second surrogate */ if (Py_UNICODE_IS_LOW_SURROGATE(outCh)) { Py_UCS4 ch2 = Py_UNICODE_JOIN_SURROGATES(surrogate, outCh); - if (unicode_putchar(&unicode, &outpos, ch2) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, ch2) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, ch2); + writer.pos++; surrogate = 0; continue; } else { - if (unicode_putchar(&unicode, &outpos, surrogate) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, surrogate) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, surrogate); + writer.pos++; surrogate = 0; } } @@ -4218,8 +4248,10 @@ surrogate = outCh; } else { - if (unicode_putchar(&unicode, &outpos, outCh) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, outCh) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, outCh); + writer.pos++; } } } @@ -4227,8 +4259,10 @@ inShift = 0; s++; if (surrogate) { - if (unicode_putchar(&unicode, &outpos, surrogate) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, surrogate) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, surrogate); + writer.pos++; surrogate = 0; } if (base64bits > 0) { /* left-over bits */ @@ -4248,8 +4282,10 @@ if (ch != '-') { /* '-' is absorbed; other terminating characters are preserved */ - if (unicode_putchar(&unicode, &outpos, ch) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, ch) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, ch); + writer.pos++; } } } @@ -4258,19 +4294,23 @@ s++; /* consume '+' */ if (s < e && *s == '-') { /* '+-' encodes '+' */ s++; - if (unicode_putchar(&unicode, &outpos, '+') < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, '+') == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, '+'); + writer.pos++; } else { /* begin base64-encoded section */ inShift = 1; - shiftOutStart = outpos; + shiftOutStart = writer.pos; base64bits = 0; } } else if (DECODE_DIRECT(ch)) { /* character decodes as itself */ - if (unicode_putchar(&unicode, &outpos, ch) < 0) + s++; + if (_PyUnicodeWriter_Prepare(&writer, 1, ch) == -1) goto onError; - s++; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, ch); + writer.pos++; } else { startinpos = s-starts; @@ -4281,11 +4321,11 @@ continue; utf7Error: endinpos = s-starts; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "utf7", errmsg, &starts, &e, &startinpos, &endinpos, &exc, &s, - &unicode, &outpos)) + &writer)) goto onError; } @@ -4297,11 +4337,11 @@ (base64bits >= 6) || (base64bits > 0 && base64buffer != 0)) { endinpos = size; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "utf7", "unterminated shift sequence", &starts, &e, &startinpos, &endinpos, &exc, &s, - &unicode, &outpos)) + &writer)) goto onError; if (s < e) goto restart; @@ -4311,7 +4351,7 @@ /* return state */ if (consumed) { if (inShift) { - outpos = shiftOutStart; /* back off output */ + writer.pos = shiftOutStart; /* back off output */ *consumed = startinpos; } else { @@ -4319,17 +4359,14 @@ } } - if (unicode_resize(&unicode, outpos) < 0) - goto onError; - Py_XDECREF(errorHandler); Py_XDECREF(exc); - return unicode_result(unicode); + return _PyUnicodeWriter_Finish(&writer); onError: Py_XDECREF(errorHandler); Py_XDECREF(exc); - Py_DECREF(unicode); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } @@ -4555,10 +4592,9 @@ const char *errors, Py_ssize_t *consumed) { - PyObject *unicode; + _PyUnicodeWriter writer; const char *starts = s; const char *end = s + size; - Py_ssize_t outpos; Py_ssize_t startinpos; Py_ssize_t endinpos; @@ -4580,29 +4616,25 @@ return get_latin1_char((unsigned char)s[0]); } - unicode = PyUnicode_New(size, 127); - if (!unicode) - return NULL; - - outpos = ascii_decode(s, end, PyUnicode_1BYTE_DATA(unicode)); - s += outpos; + _PyUnicodeWriter_Init(&writer, 0); + if (_PyUnicodeWriter_Prepare(&writer, size, 127) == -1) + goto onError; + + writer.pos = ascii_decode(s, end, writer.data); + s += writer.pos; while (s < end) { Py_UCS4 ch; - int kind = PyUnicode_KIND(unicode); + int kind = writer.kind; if (kind == PyUnicode_1BYTE_KIND) { - if (PyUnicode_IS_ASCII(unicode)) - ch = asciilib_utf8_decode(&s, end, - PyUnicode_1BYTE_DATA(unicode), &outpos); + if (PyUnicode_IS_ASCII(writer.buffer)) + ch = asciilib_utf8_decode(&s, end, writer.data, &writer.pos); else - ch = ucs1lib_utf8_decode(&s, end, - PyUnicode_1BYTE_DATA(unicode), &outpos); + ch = ucs1lib_utf8_decode(&s, end, writer.data, &writer.pos); } else if (kind == PyUnicode_2BYTE_KIND) { - ch = ucs2lib_utf8_decode(&s, end, - PyUnicode_2BYTE_DATA(unicode), &outpos); + ch = ucs2lib_utf8_decode(&s, end, writer.data, &writer.pos); } else { assert(kind == PyUnicode_4BYTE_KIND); - ch = ucs4lib_utf8_decode(&s, end, - PyUnicode_4BYTE_DATA(unicode), &outpos); + ch = ucs4lib_utf8_decode(&s, end, writer.data, &writer.pos); } switch (ch) { @@ -4626,35 +4658,33 @@ endinpos = startinpos + ch - 1; break; default: - if (unicode_putchar(&unicode, &outpos, ch) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, ch) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, ch); + writer.pos++; continue; } - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "utf-8", errmsg, &starts, &end, &startinpos, &endinpos, &exc, &s, - &unicode, &outpos)) + &writer)) goto onError; } End: - if (unicode_resize(&unicode, outpos) < 0) - goto onError; - if (consumed) *consumed = s - starts; Py_XDECREF(errorHandler); Py_XDECREF(exc); - assert(_PyUnicode_CheckConsistency(unicode, 1)); - return unicode; + return _PyUnicodeWriter_Finish(&writer); onError: Py_XDECREF(errorHandler); Py_XDECREF(exc); - Py_XDECREF(unicode); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } @@ -4799,8 +4829,7 @@ const char *starts = s; Py_ssize_t startinpos; Py_ssize_t endinpos; - Py_ssize_t outpos; - PyObject *unicode; + _PyUnicodeWriter writer; const unsigned char *q, *e; int le, bo = 0; /* assume native ordering by default */ const char *errmsg = ""; @@ -4844,25 +4873,25 @@ le = bo <= 0; #endif - unicode = PyUnicode_New((e - q + 3) / 4, 127); - if (!unicode) - return NULL; - - outpos = 0; + _PyUnicodeWriter_Init(&writer, 0); + if (_PyUnicodeWriter_Prepare(&writer, (e - q + 3) / 4, 127) == -1) + goto onError; + while (1) { Py_UCS4 ch = 0; - Py_UCS4 maxch = PyUnicode_MAX_CHAR_VALUE(unicode); + Py_UCS4 maxch = PyUnicode_MAX_CHAR_VALUE(writer.buffer); if (e - q >= 4) { - enum PyUnicode_Kind kind = PyUnicode_KIND(unicode); - void *data = PyUnicode_DATA(unicode); + enum PyUnicode_Kind kind = writer.kind; + void *data = writer.data; const unsigned char *last = e - 4; + Py_ssize_t pos = writer.pos; if (le) { do { ch = (q[3] << 24) | (q[2] << 16) | (q[1] << 8) | q[0]; if (ch > maxch) break; - PyUnicode_WRITE(kind, data, outpos++, ch); + PyUnicode_WRITE(kind, data, pos++, ch); q += 4; } while (q <= last); } @@ -4871,10 +4900,11 @@ ch = (q[0] << 24) | (q[1] << 16) | (q[2] << 8) | q[3]; if (ch > maxch) break; - PyUnicode_WRITE(kind, data, outpos++, ch); + PyUnicode_WRITE(kind, data, pos++, ch); q += 4; } while (q <= last); } + writer.pos = pos; } if (ch <= maxch) { @@ -4887,8 +4917,10 @@ } else { if (ch < 0x110000) { - if (unicode_putchar(&unicode, &outpos, ch) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, ch) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, ch); + writer.pos++; q += 4; continue; } @@ -4899,27 +4931,23 @@ /* The remaining input chars are ignored if the callback chooses to skip the input */ - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "utf32", errmsg, &starts, (const char **)&e, &startinpos, &endinpos, &exc, (const char **)&q, - &unicode, &outpos)) + &writer)) goto onError; } if (consumed) *consumed = (const char *)q-starts; - /* Adjust length */ - if (unicode_resize(&unicode, outpos) < 0) - goto onError; - Py_XDECREF(errorHandler); Py_XDECREF(exc); - return unicode_result(unicode); + return _PyUnicodeWriter_Finish(&writer); onError: - Py_DECREF(unicode); + _PyUnicodeWriter_Dealloc(&writer); Py_XDECREF(errorHandler); Py_XDECREF(exc); return NULL; @@ -5040,8 +5068,7 @@ const char *starts = s; Py_ssize_t startinpos; Py_ssize_t endinpos; - Py_ssize_t outpos; - PyObject *unicode; + _PyUnicodeWriter writer; const unsigned char *q, *e; int bo = 0; /* assume native ordering by default */ int native_ordering; @@ -5088,32 +5115,31 @@ /* Note: size will always be longer than the resulting Unicode character count */ - unicode = PyUnicode_New((e - q + 1) / 2, 127); - if (!unicode) - return NULL; - - outpos = 0; + _PyUnicodeWriter_Init(&writer, 0); + if (_PyUnicodeWriter_Prepare(&writer, (e - q + 1) / 2, 127) == -1) + goto onError; + while (1) { Py_UCS4 ch = 0; if (e - q >= 2) { - int kind = PyUnicode_KIND(unicode); + int kind = writer.kind; if (kind == PyUnicode_1BYTE_KIND) { - if (PyUnicode_IS_ASCII(unicode)) + if (PyUnicode_IS_ASCII(writer.buffer)) ch = asciilib_utf16_decode(&q, e, - PyUnicode_1BYTE_DATA(unicode), &outpos, + (Py_UCS1*)writer.data, &writer.pos, native_ordering); else ch = ucs1lib_utf16_decode(&q, e, - PyUnicode_1BYTE_DATA(unicode), &outpos, + (Py_UCS1*)writer.data, &writer.pos, native_ordering); } else if (kind == PyUnicode_2BYTE_KIND) { ch = ucs2lib_utf16_decode(&q, e, - PyUnicode_2BYTE_DATA(unicode), &outpos, + (Py_UCS2*)writer.data, &writer.pos, native_ordering); } else { assert(kind == PyUnicode_4BYTE_KIND); ch = ucs4lib_utf16_decode(&q, e, - PyUnicode_4BYTE_DATA(unicode), &outpos, + (Py_UCS4*)writer.data, &writer.pos, native_ordering); } } @@ -5146,12 +5172,14 @@ endinpos = startinpos + 2; break; default: - if (unicode_putchar(&unicode, &outpos, ch) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, ch) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, ch); + writer.pos++; continue; } - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "utf16", errmsg, @@ -5161,8 +5189,7 @@ &endinpos, &exc, (const char **)&q, - &unicode, - &outpos)) + &writer)) goto onError; } @@ -5170,16 +5197,12 @@ if (consumed) *consumed = (const char *)q-starts; - /* Adjust length */ - if (unicode_resize(&unicode, outpos) < 0) - goto onError; - Py_XDECREF(errorHandler); Py_XDECREF(exc); - return unicode_result(unicode); + return _PyUnicodeWriter_Finish(&writer); onError: - Py_DECREF(unicode); + _PyUnicodeWriter_Dealloc(&writer); Py_XDECREF(errorHandler); Py_XDECREF(exc); return NULL; @@ -5346,27 +5369,30 @@ Py_ssize_t startinpos; Py_ssize_t endinpos; int j; - PyObject *v; + _PyUnicodeWriter writer; const char *end; char* message; Py_UCS4 chr = 0xffffffff; /* in case 'getcode' messes up */ PyObject *errorHandler = NULL; PyObject *exc = NULL; Py_ssize_t len; - Py_ssize_t i; len = length_of_escaped_ascii_string(s, size); + if (len == 0) { + Py_INCREF(unicode_empty); + return unicode_empty; + } /* After length_of_escaped_ascii_string() there are two alternatives, either the string is pure ASCII with named escapes like \n, etc. and we determined it's exact size (common case) or it contains \x, \u, ... escape sequences. then we create a legacy wchar string and resize it at the end of this function. */ - if (len >= 0) { - v = PyUnicode_New(len, 127); - if (!v) + _PyUnicodeWriter_Init(&writer, 0); + if (len > 0) { + if (_PyUnicodeWriter_Prepare(&writer, len, 127) == -1) goto onError; - assert(PyUnicode_KIND(v) == PyUnicode_1BYTE_KIND); + assert(writer.kind == PyUnicode_1BYTE_KIND); } else { /* Escaped strings will always be longer than the resulting @@ -5374,15 +5400,12 @@ length after conversion to the true value. (but if the error callback returns a long replacement string we'll have to allocate more space) */ - v = PyUnicode_New(size, 127); - if (!v) + if (_PyUnicodeWriter_Prepare(&writer, size, 127) == -1) goto onError; - len = size; } if (size == 0) - return v; - i = 0; + return _PyUnicodeWriter_Finish(&writer); end = s + size; while (s < end) { @@ -5390,14 +5413,14 @@ Py_UCS4 x; int digits; - /* The only case in which i == ascii_length is a backslash - followed by a newline. */ - assert(i <= len); - /* Non-escape characters are interpreted as Unicode ordinals */ if (*s != '\\') { - if (unicode_putchar(&v, &i, (unsigned char) *s++) < 0) + x = (unsigned char)*s; + s++; + if (_PyUnicodeWriter_Prepare(&writer, 1, x) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, x); + writer.pos++; continue; } @@ -5410,16 +5433,18 @@ /* The only case in which i == ascii_length is a backslash followed by a newline. */ - assert(i < len || (i == len && c == '\n')); + assert(writer.pos < writer.size || (writer.pos == writer.size && c == '\n')); switch (c) { /* \x escapes */ -#define WRITECHAR(ch) \ - do { \ - if (unicode_putchar(&v, &i, ch) < 0) \ - goto onError; \ - }while(0) +#define WRITECHAR(ch) \ + do { \ + if (_PyUnicodeWriter_Prepare(&writer, 1, ch) == -1) \ + goto onError; \ + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, ch); \ + writer.pos++; \ + } while(0) case '\n': break; case '\\': WRITECHAR('\\'); break; @@ -5469,11 +5494,11 @@ chr = 0; if (s+digits>end) { endinpos = size; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "unicodeescape", "end of string in escape sequence", &starts, &end, &startinpos, &endinpos, &exc, &s, - &v, &i)) + &writer)) goto onError; goto nextByte; } @@ -5481,13 +5506,12 @@ c = (unsigned char) s[j]; if (!Py_ISXDIGIT(c)) { endinpos = (s+j+1)-starts; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "unicodeescape", message, &starts, &end, &startinpos, &endinpos, &exc, &s, - &v, &i)) + &writer)) goto onError; - len = PyUnicode_GET_LENGTH(v); goto nextByte; } chr = (chr<<4) & ~0xF; @@ -5509,11 +5533,11 @@ WRITECHAR(chr); } else { endinpos = s-starts; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "unicodeescape", "illegal Unicode character", &starts, &end, &startinpos, &endinpos, &exc, &s, - &v, &i)) + &writer)) goto onError; } break; @@ -5543,11 +5567,11 @@ } } endinpos = s-starts; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "unicodeescape", message, &starts, &end, &startinpos, &endinpos, &exc, &s, - &v, &i)) + &writer)) goto onError; break; @@ -5556,11 +5580,11 @@ message = "\\ at end of string"; s--; endinpos = s-starts; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "unicodeescape", message, &starts, &end, &startinpos, &endinpos, &exc, &s, - &v, &i)) + &writer)) goto onError; } else { @@ -5574,24 +5598,22 @@ } #undef WRITECHAR - if (unicode_resize(&v, i) < 0) - goto onError; Py_XDECREF(errorHandler); Py_XDECREF(exc); - return unicode_result(v); + return _PyUnicodeWriter_Finish(&writer); ucnhashError: PyErr_SetString( PyExc_UnicodeError, "\\N escapes not supported (can't load unicodedata module)" ); - Py_XDECREF(v); + _PyUnicodeWriter_Dealloc(&writer); Py_XDECREF(errorHandler); Py_XDECREF(exc); return NULL; onError: - Py_XDECREF(v); + _PyUnicodeWriter_Dealloc(&writer); Py_XDECREF(errorHandler); Py_XDECREF(exc); return NULL; @@ -5744,23 +5766,25 @@ const char *starts = s; Py_ssize_t startinpos; Py_ssize_t endinpos; - Py_ssize_t outpos; - PyObject *v; + _PyUnicodeWriter writer; const char *end; const char *bs; PyObject *errorHandler = NULL; PyObject *exc = NULL; + if (size == 0) { + Py_INCREF(unicode_empty); + return unicode_empty; + } + /* Escaped strings will always be longer than the resulting Unicode string, so we start with size here and then reduce the length after conversion to the true value. (But decoding error handler might have to resize the string) */ - v = PyUnicode_New(size, 127); - if (v == NULL) + _PyUnicodeWriter_Init(&writer, 1); + if (_PyUnicodeWriter_Prepare(&writer, size, 127) == -1) goto onError; - if (size == 0) - return v; - outpos = 0; + end = s + size; while (s < end) { unsigned char c; @@ -5770,8 +5794,11 @@ /* Non-escape characters are interpreted as Unicode ordinals */ if (*s != '\\') { - if (unicode_putchar(&v, &outpos, (unsigned char)*s++) < 0) + x = (unsigned char)*s++; + if (_PyUnicodeWriter_Prepare(&writer, 1, x) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, x); + writer.pos++; continue; } startinpos = s-starts; @@ -5782,15 +5809,18 @@ for (;s < end;) { if (*s != '\\') break; - if (unicode_putchar(&v, &outpos, (unsigned char)*s++) < 0) + x = (unsigned char)*s++; + if (_PyUnicodeWriter_Prepare(&writer, 1, x) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, x); + writer.pos++; } if (((s - bs) & 1) == 0 || s >= end || (*s != 'u' && *s != 'U')) { continue; } - outpos--; + writer.pos--; count = *s=='u' ? 4 : 8; s++; @@ -5799,11 +5829,11 @@ c = (unsigned char)*s; if (!Py_ISXDIGIT(c)) { endinpos = s-starts; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "rawunicodeescape", "truncated \\uXXXX", &starts, &end, &startinpos, &endinpos, &exc, &s, - &v, &outpos)) + &writer)) goto onError; goto nextByte; } @@ -5816,28 +5846,29 @@ x += 10 + c - 'A'; } if (x <= MAX_UNICODE) { - if (unicode_putchar(&v, &outpos, x) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, x) == -1) goto onError; - } else { + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, x); + writer.pos++; + } + else { endinpos = s-starts; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "rawunicodeescape", "\\Uxxxxxxxx out of range", &starts, &end, &startinpos, &endinpos, &exc, &s, - &v, &outpos)) + &writer)) goto onError; } nextByte: ; } - if (unicode_resize(&v, outpos) < 0) - goto onError; Py_XDECREF(errorHandler); Py_XDECREF(exc); - return unicode_result(v); + return _PyUnicodeWriter_Finish(&writer); onError: - Py_XDECREF(v); + _PyUnicodeWriter_Dealloc(&writer); Py_XDECREF(errorHandler); Py_XDECREF(exc); return NULL; @@ -5937,8 +5968,7 @@ const char *starts = s; Py_ssize_t startinpos; Py_ssize_t endinpos; - Py_ssize_t outpos; - PyObject *v; + _PyUnicodeWriter writer; const char *end; const char *reason; PyObject *errorHandler = NULL; @@ -5949,13 +5979,15 @@ 1)) return NULL; + if (size == 0) { + Py_INCREF(unicode_empty); + return unicode_empty; + } + /* XXX overflow detection missing */ - v = PyUnicode_New((size+Py_UNICODE_SIZE-1)/ Py_UNICODE_SIZE, 127); - if (v == NULL) + _PyUnicodeWriter_Init(&writer, 0); + if (_PyUnicodeWriter_Prepare(&writer, (size+Py_UNICODE_SIZE-1)/ Py_UNICODE_SIZE, 127) == -1) goto onError; - if (PyUnicode_GET_LENGTH(v) == 0) - return v; - outpos = 0; end = s + size; while (s < end) { @@ -5989,11 +6021,11 @@ endinpos = s - starts + Py_UNICODE_SIZE; reason = "illegal code point (> 0x10FFFF)"; } - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "unicode_internal", reason, &starts, &end, &startinpos, &endinpos, &exc, &s, - &v, &outpos)) + &writer)) goto onError; continue; } @@ -6013,18 +6045,18 @@ } #endif - if (unicode_putchar(&v, &outpos, ch) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, ch) == -1) goto onError; - } - - if (unicode_resize(&v, outpos) < 0) - goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, ch); + writer.pos++; + } + Py_XDECREF(errorHandler); Py_XDECREF(exc); - return unicode_result(v); + return _PyUnicodeWriter_Finish(&writer); onError: - Py_XDECREF(v); + _PyUnicodeWriter_Dealloc(&writer); Py_XDECREF(errorHandler); Py_XDECREF(exc); return NULL; @@ -6388,7 +6420,7 @@ const char *errors) { const char *starts = s; - PyObject *unicode; + _PyUnicodeWriter writer; int kind; void *data; Py_ssize_t startinpos; @@ -6407,46 +6439,45 @@ if (size == 1 && (unsigned char)s[0] < 128) return get_latin1_char((unsigned char)s[0]); - unicode = PyUnicode_New(size, 127); - if (unicode == NULL) + _PyUnicodeWriter_Init(&writer, 0); + if (_PyUnicodeWriter_Prepare(&writer, size, 127) == -1) goto onError; e = s + size; - data = PyUnicode_1BYTE_DATA(unicode); + data = writer.data; outpos = ascii_decode(s, e, (Py_UCS1 *)data); - if (outpos == size) - return unicode; - - s += outpos; - kind = PyUnicode_1BYTE_KIND; + writer.pos = outpos; + if (writer.pos == size) + return _PyUnicodeWriter_Finish(&writer); + + s += writer.pos; + kind = writer.kind; while (s < e) { register unsigned char c = (unsigned char)*s; if (c < 128) { - PyUnicode_WRITE(kind, data, outpos++, c); + PyUnicode_WRITE(kind, data, writer.pos, c); + writer.pos++; ++s; } else { startinpos = s-starts; endinpos = startinpos + 1; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "ascii", "ordinal not in range(128)", &starts, &e, &startinpos, &endinpos, &exc, &s, - &unicode, &outpos)) + &writer)) goto onError; - kind = PyUnicode_KIND(unicode); - data = PyUnicode_DATA(unicode); - } - } - if (unicode_resize(&unicode, outpos) < 0) - goto onError; + kind = writer.kind; + data = writer.data; + } + } Py_XDECREF(errorHandler); Py_XDECREF(exc); - assert(_PyUnicode_CheckConsistency(unicode, 1)); - return unicode; + return _PyUnicodeWriter_Finish(&writer); onError: - Py_XDECREF(unicode); + _PyUnicodeWriter_Dealloc(&writer); Py_XDECREF(errorHandler); Py_XDECREF(exc); return NULL; @@ -6707,7 +6738,7 @@ startinpos = in - startin; endinpos = startinpos + 1; outpos = out - PyUnicode_AS_UNICODE(*v); - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_wchar( errors, &errorHandler, encoding, reason, &startin, &endin, &startinpos, &endinpos, &exc, &in, @@ -7249,10 +7280,8 @@ const char *starts = s; Py_ssize_t startinpos; Py_ssize_t endinpos; - Py_ssize_t outpos; const char *e; - PyObject *v; - Py_ssize_t extrachars = 0; + _PyUnicodeWriter writer; PyObject *errorHandler = NULL; PyObject *exc = NULL; @@ -7260,12 +7289,14 @@ if (mapping == NULL) return PyUnicode_DecodeLatin1(s, size, errors); - v = PyUnicode_New(size, 127); - if (v == NULL) + if (size == 0) { + Py_INCREF(unicode_empty); + return unicode_empty; + } + _PyUnicodeWriter_Init(&writer, 0); + if (_PyUnicodeWriter_Prepare(&writer, size, 127) == -1) goto onError; - if (size == 0) - return v; - outpos = 0; + e = s + size; if (PyUnicode_CheckExact(mapping)) { Py_ssize_t maplen; @@ -7282,28 +7313,29 @@ while (s < e) { unsigned char ch; if (mapkind == PyUnicode_2BYTE_KIND && maplen >= 256) { - enum PyUnicode_Kind outkind = PyUnicode_KIND(v); + enum PyUnicode_Kind outkind = writer.kind; + void *outdata = writer.data; if (outkind == PyUnicode_1BYTE_KIND) { - void *outdata = PyUnicode_DATA(v); - Py_UCS4 maxchar = PyUnicode_MAX_CHAR_VALUE(v); + Py_UCS4 maxchar = writer.maxchar; while (s < e) { unsigned char ch = *s; x = PyUnicode_READ(PyUnicode_2BYTE_KIND, mapdata, ch); if (x > maxchar) goto Error; - PyUnicode_WRITE(PyUnicode_1BYTE_KIND, outdata, outpos++, x); + PyUnicode_WRITE(PyUnicode_1BYTE_KIND, outdata, writer.pos, x); + writer.pos++; ++s; } break; } else if (outkind == PyUnicode_2BYTE_KIND) { - void *outdata = PyUnicode_DATA(v); while (s < e) { unsigned char ch = *s; x = PyUnicode_READ(PyUnicode_2BYTE_KIND, mapdata, ch); if (x == 0xFFFE) goto Error; - PyUnicode_WRITE(PyUnicode_2BYTE_KIND, outdata, outpos++, x); + PyUnicode_WRITE(PyUnicode_2BYTE_KIND, outdata, writer.pos, x); + writer.pos++; ++s; } break; @@ -7321,18 +7353,20 @@ /* undefined mapping */ startinpos = s-starts; endinpos = startinpos+1; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "charmap", "character maps to ", &starts, &e, &startinpos, &endinpos, &exc, &s, - &v, &outpos)) { + &writer)) { goto onError; } continue; } - if (unicode_putchar(&v, &outpos, x) < 0) + if (_PyUnicodeWriter_Prepare(&writer, 1, x) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, x); + writer.pos++; ++s; } } @@ -7367,18 +7401,21 @@ Py_DECREF(x); goto onError; } - if (unicode_putchar(&v, &outpos, value) < 0) + + if (_PyUnicodeWriter_Prepare(&writer, 1, value) == -1) goto onError; + PyUnicode_WRITE(writer.kind, writer.data, writer.pos, value); + writer.pos++; } else if (x == Py_None) { /* undefined mapping */ startinpos = s-starts; endinpos = startinpos+1; - if (unicode_decode_call_errorhandler( + if (unicode_decode_call_errorhandler_writer( errors, &errorHandler, "charmap", "character maps to ", &starts, &e, &startinpos, &endinpos, &exc, &s, - &v, &outpos)) { + &writer)) { Py_DECREF(x); goto onError; } @@ -7386,40 +7423,9 @@ continue; } else if (PyUnicode_Check(x)) { - Py_ssize_t targetsize; - - if (PyUnicode_READY(x) == -1) + writer.overallocate = 1; + if (_PyUnicodeWriter_WriteStr(&writer, x) == -1) goto onError; - targetsize = PyUnicode_GET_LENGTH(x); - - if (targetsize == 1) { - /* 1-1 mapping */ - if (unicode_putchar(&v, &outpos, - PyUnicode_READ_CHAR(x, 0)) < 0) - goto onError; - } - else if (targetsize > 1) { - /* 1-n mapping */ - if (targetsize > extrachars) { - /* resize first */ - Py_ssize_t needed = (targetsize - extrachars) + \ - (targetsize << 2); - extrachars += needed; - /* XXX overflow detection missing */ - if (unicode_resize(&v, - PyUnicode_GET_LENGTH(v) + needed) < 0) - { - Py_DECREF(x); - goto onError; - } - } - if (unicode_widen(&v, outpos, PyUnicode_MAX_CHAR_VALUE(x)) < 0) - goto onError; - PyUnicode_CopyCharacters(v, outpos, x, 0, targetsize); - outpos += targetsize; - extrachars -= targetsize; - } - /* 1-0 mapping: skip the character */ } else { /* wrong return value */ @@ -7432,16 +7438,14 @@ ++s; } } - if (unicode_resize(&v, outpos) < 0) - goto onError; Py_XDECREF(errorHandler); Py_XDECREF(exc); - return unicode_result(v); + return _PyUnicodeWriter_Finish(&writer); onError: Py_XDECREF(errorHandler); Py_XDECREF(exc); - Py_XDECREF(v); + _PyUnicodeWriter_Dealloc(&writer); return NULL; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 00:57:12 2012 From: python-checkins at python.org (victor.stinner) Date: Wed, 7 Nov 2012 00:57:12 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython=3A_Remove_outdated_comment?= Message-ID: <3Xx73D6HGCzM34@mail.python.org> http://hg.python.org/cpython/rev/7d5f35326a77 changeset: 80288:7d5f35326a77 user: Victor Stinner date: Wed Nov 07 00:57:26 2012 +0100 summary: Remove outdated comment files: Lib/test/test_cmd_line_script.py | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/Lib/test/test_cmd_line_script.py b/Lib/test/test_cmd_line_script.py --- a/Lib/test/test_cmd_line_script.py +++ b/Lib/test/test_cmd_line_script.py @@ -366,7 +366,6 @@ @unittest.skipUnless(support.TESTFN_NONASCII, 'need support.TESTFN_NONASCII') def test_non_ascii(self): # Issue #16218 - # non-ascii filename encodable to cp1252, cp932, latin1 and utf8 source = 'print(ascii(__file__))\n' script_name = _make_test_script(os.curdir, support.TESTFN_NONASCII, source) self.addCleanup(support.unlink, script_name) -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Wed Nov 7 05:56:36 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Wed, 07 Nov 2012 05:56:36 +0100 Subject: [Python-checkins] Daily reference leaks (7d5f35326a77): sum=2 Message-ID: results for 7d5f35326a77 on branch "default" -------------------------------------------- test_dbm leaked [0, 2, 0] references, sum=2 Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflogxdONoJ', '-x'] From python-checkins at python.org Wed Nov 7 09:14:30 2012 From: python-checkins at python.org (hynek.schlawack) Date: Wed, 7 Nov 2012 09:14:30 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE1MDAx?= =?utf-8?b?OiBmaXggc2VnZmF1bHQgb24gImRlbCBzeXMubW9kdWxlWydfX21haW5fXydd?= =?utf-8?q?=22?= Message-ID: <3XxL52116ZzMnP@mail.python.org> http://hg.python.org/cpython/rev/b256d054f229 changeset: 80289:b256d054f229 branch: 3.2 parent: 80268:0dfa3b09a6fe user: Hynek Schlawack date: Wed Nov 07 09:02:24 2012 +0100 summary: Issue #15001: fix segfault on "del sys.module['__main__']" Patch by Victor Stinner. files: Lib/test/test_cmd_line.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Python/pythonrun.c | 12 ++++++------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -364,6 +364,18 @@ self.assertEqual(rc, 0) self.assertIn(b'random is 1', out) + def test_del___main__(self): + # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a + # borrowed reference to the dict of __main__ module and later modify + # the dict whereas the module was destroyed + filename = test.support.TESTFN + self.addCleanup(test.support.unlink, filename) + with open(filename, "w") as script: + print("import sys", file=script) + print("del sys.modules['__main__']", file=script) + assert_python_ok(filename) + + def test_main(): test.support.run_unittest(CmdLineTest) test.support.reap_children() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #15001: fix segfault on "del sys.module['__main__']". Patch by Victor + Stinner. + - Issue #5057: the peepholer no longer optimizes subscription on unicode literals (e.g. u'foo'[0]) in order to produce compatible pyc files between narrow and wide builds. diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1257,25 +1257,26 @@ { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, ret; + int set_file_name = 0, ret = -1; size_t len; m = PyImport_AddModule("__main__"); if (m == NULL) return -1; + Py_INCREF(m); d = PyModule_GetDict(m); if (PyDict_GetItemString(d, "__file__") == NULL) { PyObject *f; f = PyUnicode_DecodeFSDefault(filename); if (f == NULL) - return -1; + goto done; if (PyDict_SetItemString(d, "__file__", f) < 0) { Py_DECREF(f); - return -1; + goto done; } if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) { Py_DECREF(f); - return -1; + goto done; } set_file_name = 1; Py_DECREF(f); @@ -1288,7 +1289,6 @@ fclose(fp); if ((fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); - ret = -1; goto done; } /* Turn on optimization if a .pyo file is given */ @@ -1302,7 +1302,6 @@ flush_io(); if (v == NULL) { PyErr_Print(); - ret = -1; goto done; } Py_DECREF(v); @@ -1310,6 +1309,7 @@ done: if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); + Py_DECREF(m); return ret; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 09:14:31 2012 From: python-checkins at python.org (hynek.schlawack) Date: Wed, 7 Nov 2012 09:14:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Issue_=2315001=3A_fix_segfault_on_=22del_sys=2Emodule=5B=27=5F?= =?utf-8?b?X21haW5fXyddIg==?= Message-ID: <3XxL533XqZzPK9@mail.python.org> http://hg.python.org/cpython/rev/215297665098 changeset: 80290:215297665098 branch: 3.3 parent: 80282:55cc29d7e83a parent: 80289:b256d054f229 user: Hynek Schlawack date: Wed Nov 07 09:07:22 2012 +0100 summary: Issue #15001: fix segfault on "del sys.module['__main__']" Patch by Victor Stinner. files: Lib/test/test_cmd_line.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Python/pythonrun.c | 12 ++++++------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -358,6 +358,18 @@ self.assertEqual(rc, 0) self.assertIn(b'random is 1', out) + def test_del___main__(self): + # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a + # borrowed reference to the dict of __main__ module and later modify + # the dict whereas the module was destroyed + filename = test.support.TESTFN + self.addCleanup(test.support.unlink, filename) + with open(filename, "w") as script: + print("import sys", file=script) + print("del sys.modules['__main__']", file=script) + assert_python_ok(filename) + + def test_main(): test.support.run_unittest(CmdLineTest) test.support.reap_children() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,9 @@ Core and Builtins ----------------- +- Issue #15001: fix segfault on "del sys.module['__main__']". Patch by Victor + Stinner. + - Issue #8271: the utf-8 decoder now outputs the correct number of U+FFFD characters when used with the 'replace' error handler on invalid utf-8 sequences. Patch by Serhiy Storchaka, tests by Ezio Melotti. diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1390,25 +1390,26 @@ { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, ret; + int set_file_name = 0, ret = -1; size_t len; m = PyImport_AddModule("__main__"); if (m == NULL) return -1; + Py_INCREF(m); d = PyModule_GetDict(m); if (PyDict_GetItemString(d, "__file__") == NULL) { PyObject *f; f = PyUnicode_DecodeFSDefault(filename); if (f == NULL) - return -1; + goto done; if (PyDict_SetItemString(d, "__file__", f) < 0) { Py_DECREF(f); - return -1; + goto done; } if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) { Py_DECREF(f); - return -1; + goto done; } set_file_name = 1; Py_DECREF(f); @@ -1422,7 +1423,6 @@ fclose(fp); if ((pyc_fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); - ret = -1; goto done; } /* Turn on optimization if a .pyo file is given */ @@ -1451,7 +1451,6 @@ flush_io(); if (v == NULL) { PyErr_Print(); - ret = -1; goto done; } Py_DECREF(v); @@ -1459,6 +1458,7 @@ done: if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); + Py_DECREF(m); return ret; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 09:14:32 2012 From: python-checkins at python.org (hynek.schlawack) Date: Wed, 7 Nov 2012 09:14:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Issue_=2315001=3A_fix_segfault_on_=22del_sys=2Emodule=5B?= =?utf-8?b?J19fbWFpbl9fJ10i?= Message-ID: <3XxL545vHyzPVg@mail.python.org> http://hg.python.org/cpython/rev/859ef54bdce2 changeset: 80291:859ef54bdce2 parent: 80288:7d5f35326a77 parent: 80290:215297665098 user: Hynek Schlawack date: Wed Nov 07 09:10:49 2012 +0100 summary: Issue #15001: fix segfault on "del sys.module['__main__']" Patch by Victor Stinner. files: Lib/test/test_cmd_line.py | 12 ++++++++++++ Misc/NEWS | 3 +++ Python/pythonrun.c | 12 ++++++------ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -375,6 +375,18 @@ self.assertEqual(rc, 0) self.assertIn(b'random is 1', out) + def test_del___main__(self): + # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a + # borrowed reference to the dict of __main__ module and later modify + # the dict whereas the module was destroyed + filename = test.support.TESTFN + self.addCleanup(test.support.unlink, filename) + with open(filename, "w") as script: + print("import sys", file=script) + print("del sys.modules['__main__']", file=script) + assert_python_ok(filename) + + def test_main(): test.support.run_unittest(CmdLineTest) test.support.reap_children() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ Core and Builtins ----------------- +- Issue #15001: fix segfault on "del sys.module['__main__']". Patch by Victor + Stinner. + - Issue #8271: the utf-8 decoder now outputs the correct number of U+FFFD characters when used with the 'replace' error handler on invalid utf-8 sequences. Patch by Serhiy Storchaka, tests by Ezio Melotti. diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -1390,25 +1390,26 @@ { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, ret; + int set_file_name = 0, ret = -1; size_t len; m = PyImport_AddModule("__main__"); if (m == NULL) return -1; + Py_INCREF(m); d = PyModule_GetDict(m); if (PyDict_GetItemString(d, "__file__") == NULL) { PyObject *f; f = PyUnicode_DecodeFSDefault(filename); if (f == NULL) - return -1; + goto done; if (PyDict_SetItemString(d, "__file__", f) < 0) { Py_DECREF(f); - return -1; + goto done; } if (PyDict_SetItemString(d, "__cached__", Py_None) < 0) { Py_DECREF(f); - return -1; + goto done; } set_file_name = 1; Py_DECREF(f); @@ -1422,7 +1423,6 @@ fclose(fp); if ((pyc_fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); - ret = -1; goto done; } /* Turn on optimization if a .pyo file is given */ @@ -1451,7 +1451,6 @@ flush_io(); if (v == NULL) { PyErr_Print(); - ret = -1; goto done; } Py_DECREF(v); @@ -1459,6 +1458,7 @@ done: if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); + Py_DECREF(m); return ret; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 09:42:19 2012 From: python-checkins at python.org (marc-andre.lemburg) Date: Wed, 7 Nov 2012 09:42:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Issue_=2316420=3A?= Message-ID: <3XxLj75F0vzPdc@mail.python.org> http://hg.python.org/peps/rev/95a73d5a3af7 changeset: 4578:95a73d5a3af7 user: Marc-Andre Lemburg date: Wed Nov 07 09:42:07 2012 +0100 summary: Issue #16420: Convert PEP 249 (DB-API 2.0) to ReST format to allow linking to the various parts. The conversion was done mostly by Daniele Varrazzo. files: pep-0249.txt | 1976 ++++++++++++++++++++----------------- 1 files changed, 1073 insertions(+), 903 deletions(-) diff --git a/pep-0249.txt b/pep-0249.txt --- a/pep-0249.txt +++ b/pep-0249.txt @@ -1,592 +1,699 @@ PEP: 249 Title: Python Database API Specification v2.0 -Version: $Revision: 56119 $ -Last-Modified: $Date: 2007-06-28 22:11:32 +0200 (Thu, 28 Jun 2007) $ +Version: $Revision$ +Last-Modified: $Date$ Author: mal at lemburg.com (Marc-Andr? Lemburg) Discussions-To: db-sig at python.org Status: Final Type: Informational +Content-Type: text/x-rst Created: Post-History: Replaces: 248 -Introduction - - This API has been defined to encourage similarity between the - Python modules that are used to access databases. By doing this, - we hope to achieve a consistency leading to more easily understood - modules, code that is generally more portable across databases, - and a broader reach of database connectivity from Python. - - The interface specification consists of several sections: - - * Module Interface - * Connection Objects - * Cursor Objects - * Type Objects and Constructors - * Implementation Hints for Module Authors - * Optional DB API Extensions - * Optional Error Handling Extensions - * Optional Two-Phase Commit Extensions - * Frequently Asked Questions - * Major Changes from Version 1.0 to Version 2.0 - * Open Issues - * Footnotes - * Acknowledgments - - Comments and questions about this specification may be directed - to the SIG for Database Interfacing with Python - (db-sig at python.org). - For more information on database interfacing with Python and - available packages see the Database Topic - Guide at http://www.python.org/topics/database/. +`Introduction`_ +=============== - This document describes the Python Database API Specification 2.0 - and a set of common optional extensions. The previous version 1.0 - version is still available as reference, in PEP 248. Package - writers are encouraged to use this version of the specification as - basis for new interfaces. +This API has been defined to encourage similarity between the Python +modules that are used to access databases. By doing this, we hope to +achieve a consistency leading to more easily understood modules, code +that is generally more portable across databases, and a broader reach +of database connectivity from Python. -Module Interface - - Access to the database is made available through connection - objects. The module must provide the following constructor for - these: +Comments and questions about this specification may be directed to the +`SIG for Database Interfacing with Python `__. - connect(parameters...) +For more information on database interfacing with Python and available +packages see the `Database Topic Guide +`__. - Constructor for creating a connection to the database. - Returns a Connection Object. It takes a number of - parameters which are database dependent. [1] - - These module globals must be defined: +This document describes the Python Database API Specification 2.0 and +a set of common optional extensions. The previous version 1.0 version +is still available as reference, in :PEP:`248`. Package writers are +encouraged to use this version of the specification as basis for new +interfaces. - apilevel - String constant stating the supported DB API level. - Currently only the strings '1.0' and '2.0' are allowed. - - If not given, a DB-API 1.0 level interface should be - assumed. - - threadsafety +`Module Interface`_ +=================== - Integer constant stating the level of thread safety the - interface supports. Possible values are: +`Constructors`_ +--------------- - 0 Threads may not share the module. - 1 Threads may share the module, but not connections. - 2 Threads may share the module and connections. - 3 Threads may share the module, connections and - cursors. +Access to the database is made available through connection +objects. The module must provide the following constructor for these: - Sharing in the above context means that two threads may - use a resource without wrapping it using a mutex semaphore - to implement resource locking. Note that you cannot always - make external resources thread safe by managing access - using a mutex: the resource may rely on global variables - or other external sources that are beyond your control. +.. _connect: - paramstyle - - String constant stating the type of parameter marker - formatting expected by the interface. Possible values are - [2]: +`connect`_\ ( *parameters...* ) + Constructor for creating a connection to the database. - 'qmark' Question mark style, - e.g. '...WHERE name=?' - 'numeric' Numeric, positional style, - e.g. '...WHERE name=:1' - 'named' Named style, - e.g. '...WHERE name=:name' - 'format' ANSI C printf format codes, - e.g. '...WHERE name=%s' - 'pyformat' Python extended format codes, - e.g. '...WHERE name=%(name)s' + Returns a Connection_ Object. It takes a number of parameters + which are database dependent. [1]_ - The module should make all error information available through - these exceptions or subclasses thereof: - Warning - - Exception raised for important warnings like data - truncations while inserting, etc. It must be a subclass of - the Python StandardError (defined in the module - exceptions). - - Error +`Globals`_ +---------- - Exception that is the base class of all other error - exceptions. You can use this to catch all errors with one - single 'except' statement. Warnings are not considered - errors and thus should not use this class as base. It must - be a subclass of the Python StandardError (defined in the - module exceptions). - - InterfaceError +These module globals must be defined: - Exception raised for errors that are related to the - database interface rather than the database itself. It - must be a subclass of Error. +.. _apilevel: - DatabaseError +`apilevel`_ + String constant stating the supported DB API level. - Exception raised for errors that are related to the - database. It must be a subclass of Error. - - DataError - - Exception raised for errors that are due to problems with - the processed data like division by zero, numeric value - out of range, etc. It must be a subclass of DatabaseError. - - OperationalError - - Exception raised for errors that are related to the - database's operation and not necessarily under the control - of the programmer, e.g. an unexpected disconnect occurs, - the data source name is not found, a transaction could not - be processed, a memory allocation error occurred during - processing, etc. It must be a subclass of DatabaseError. - - IntegrityError - - Exception raised when the relational integrity of the - database is affected, e.g. a foreign key check fails. It - must be a subclass of DatabaseError. - - InternalError - - Exception raised when the database encounters an internal - error, e.g. the cursor is not valid anymore, the - transaction is out of sync, etc. It must be a subclass of - DatabaseError. - - ProgrammingError - - Exception raised for programming errors, e.g. table not - found or already exists, syntax error in the SQL - statement, wrong number of parameters specified, etc. It - must be a subclass of DatabaseError. - - NotSupportedError - - Exception raised in case a method or database API was used - which is not supported by the database, e.g. requesting a - .rollback() on a connection that does not support - transaction or has transactions turned off. It must be a - subclass of DatabaseError. - - This is the exception inheritance layout: + Currently only the strings "``1.0``" and "``2.0``" are allowed. + If not given, a DB-API 1.0 level interface should be assumed. - StandardError - |__Warning - |__Error - |__InterfaceError - |__DatabaseError - |__DataError - |__OperationalError - |__IntegrityError - |__InternalError - |__ProgrammingError - |__NotSupportedError - - Note: The values of these exceptions are not defined. They should - give the user a fairly good idea of what went wrong, though. - -Connection Objects +.. _threadsafety: - Connection Objects should respond to the following methods: +`threadsafety`_ + Integer constant stating the level of thread safety the interface + supports. Possible values are: - .close() - - Close the connection now (rather than whenever __del__ is - called). The connection will be unusable from this point - forward; an Error (or subclass) exception will be raised - if any operation is attempted with the connection. The - same applies to all cursor objects trying to use the - connection. Note that closing a connection without - committing the changes first will cause an implicit - rollback to be performed. + ============ ======================================================= + threadsafety Meaning + ============ ======================================================= + 0 Threads may not share the module. + 1 Threads may share the module, but not connections. + 2 Threads may share the module and connections. + 3 Threads may share the module, connections and cursors. + ============ ======================================================= - - .commit() - - Commit any pending transaction to the database. Note that - if the database supports an auto-commit feature, this must - be initially off. An interface method may be provided to - turn it back on. - - Database modules that do not support transactions should - implement this method with void functionality. - - .rollback() - - This method is optional since not all databases provide - transaction support. [3] - - In case a database does provide transactions this method - causes the database to roll back to the start of any - pending transaction. Closing a connection without - committing the changes first will cause an implicit - rollback to be performed. - - .cursor() - - Return a new Cursor Object using the connection. If the - database does not provide a direct cursor concept, the - module will have to emulate cursors using other means to - the extent needed by this specification. [4] - + Sharing in the above context means that two threads may use a + resource without wrapping it using a mutex semaphore to implement + resource locking. Note that you cannot always make external + resources thread safe by managing access using a mutex: the + resource may rely on global variables or other external sources + that are beyond your control. -Cursor Objects - These objects represent a database cursor, which is used to manage - the context of a fetch operation. Cursors created from the same - connection are not isolated, i.e., any changes done to the - database by a cursor are immediately visible by the other - cursors. Cursors created from different connections can or can not - be isolated, depending on how the transaction support is - implemented (see also the connection's .rollback() and .commit() - methods). - - Cursor Objects should respond to the following methods and - attributes: +.. _paramstyle: - .description - - This read-only attribute is a sequence of 7-item - sequences. +`paramstyle`_ + String constant stating the type of parameter marker formatting + expected by the interface. Possible values are [2]_: - Each of these sequences contains information describing - one result column: + ============ ============================================================== + paramstyle Meaning + ============ ============================================================== + ``qmark`` Question mark style, e.g. ``...WHERE name=?`` + ``numeric`` Numeric, positional style, e.g. ``...WHERE name=:1`` + ``named`` Named style, e.g. ``...WHERE name=:name`` + ``format`` ANSI C printf format codes, e.g. ``...WHERE name=%s`` + ``pyformat`` Python extended format codes, e.g. ``...WHERE name=%(name)s`` + ============ ============================================================== - (name, - type_code, - display_size, - internal_size, - precision, - scale, - null_ok) - The first two items (name and type_code) are mandatory, - the other five are optional and are set to None if no - meaningful values can be provided. +`Exceptions`_ +------------- - This attribute will be None for operations that - do not return rows or if the cursor has not had an - operation invoked via the .execute*() method yet. - - The type_code can be interpreted by comparing it to the - Type Objects specified in the section below. - - .rowcount - - This read-only attribute specifies the number of rows that - the last .execute*() produced (for DQL statements like - 'select') or affected (for DML statements like 'update' or - 'insert'). - - The attribute is -1 in case no .execute*() has been - performed on the cursor or the rowcount of the last - operation is cannot be determined by the interface. [7] +The module should make all error information available through these +exceptions or subclasses thereof: - Note: Future versions of the DB API specification could - redefine the latter case to have the object return None - instead of -1. - - .callproc(procname[,parameters]) - - (This method is optional since not all databases provide - stored procedures. [3]) - - Call a stored database procedure with the given name. The - sequence of parameters must contain one entry for each - argument that the procedure expects. The result of the - call is returned as modified copy of the input - sequence. Input parameters are left untouched, output and - input/output parameters replaced with possibly new values. - - The procedure may also provide a result set as - output. This must then be made available through the - standard .fetch*() methods. - - .close() - - Close the cursor now (rather than whenever __del__ is - called). The cursor will be unusable from this point - forward; an Error (or subclass) exception will be raised - if any operation is attempted with the cursor. - - .execute(operation[,parameters]) - - Prepare and execute a database operation (query or - command). Parameters may be provided as sequence or - mapping and will be bound to variables in the operation. - Variables are specified in a database-specific notation - (see the module's paramstyle attribute for details). [5] - - A reference to the operation will be retained by the - cursor. If the same operation object is passed in again, - then the cursor can optimize its behavior. This is most - effective for algorithms where the same operation is used, - but different parameters are bound to it (many times). - - For maximum efficiency when reusing an operation, it is - best to use the .setinputsizes() method to specify the - parameter types and sizes ahead of time. It is legal for - a parameter to not match the predefined information; the - implementation should compensate, possibly with a loss of - efficiency. - - The parameters may also be specified as list of tuples to - e.g. insert multiple rows in a single operation, but this - kind of usage is deprecated: .executemany() should be used - instead. - - Return values are not defined. - - .executemany(operation,seq_of_parameters) - - Prepare a database operation (query or command) and then - execute it against all parameter sequences or mappings - found in the sequence seq_of_parameters. - - Modules are free to implement this method using multiple - calls to the .execute() method or by using array operations - to have the database process the sequence as a whole in - one call. - - Use of this method for an operation which produces one or - more result sets constitutes undefined behavior, and the - implementation is permitted (but not required) to raise - an exception when it detects that a result set has been - created by an invocation of the operation. - - The same comments as for .execute() also apply accordingly - to this method. - - Return values are not defined. - - .fetchone() - - Fetch the next row of a query result set, returning a - single sequence, or None when no more data is - available. [6] - - An Error (or subclass) exception is raised if the previous - call to .execute*() did not produce any result set or no - call was issued yet. +.. _Warning: - .fetchmany([size=cursor.arraysize]) - - Fetch the next set of rows of a query result, returning a - sequence of sequences (e.g. a list of tuples). An empty - sequence is returned when no more rows are available. - - The number of rows to fetch per call is specified by the - parameter. If it is not given, the cursor's arraysize - determines the number of rows to be fetched. The method - should try to fetch as many rows as indicated by the size - parameter. If this is not possible due to the specified - number of rows not being available, fewer rows may be - returned. - - An Error (or subclass) exception is raised if the previous - call to .execute*() did not produce any result set or no - call was issued yet. - - Note there are performance considerations involved with - the size parameter. For optimal performance, it is - usually best to use the arraysize attribute. If the size - parameter is used, then it is best for it to retain the - same value from one .fetchmany() call to the next. - - .fetchall() +`Warning`_ + Exception raised for important warnings like data truncations + while inserting, etc. It must be a subclass of the Python + ``StandardError`` (defined in the module exceptions). - Fetch all (remaining) rows of a query result, returning - them as a sequence of sequences (e.g. a list of tuples). - Note that the cursor's arraysize attribute can affect the - performance of this operation. - - An Error (or subclass) exception is raised if the previous - call to .execute*() did not produce any result set or no - call was issued yet. - - .nextset() - - (This method is optional since not all databases support - multiple result sets. [3]) - - This method will make the cursor skip to the next - available set, discarding any remaining rows from the - current set. - - If there are no more sets, the method returns - None. Otherwise, it returns a true value and subsequent - calls to the fetch methods will return rows from the next - result set. - - An Error (or subclass) exception is raised if the previous - call to .execute*() did not produce any result set or no - call was issued yet. - .arraysize - - This read/write attribute specifies the number of rows to - fetch at a time with .fetchmany(). It defaults to 1 - meaning to fetch a single row at a time. - - Implementations must observe this value with respect to - the .fetchmany() method, but are free to interact with the - database a single row at a time. It may also be used in - the implementation of .executemany(). - - .setinputsizes(sizes) - - This can be used before a call to .execute*() to - predefine memory areas for the operation's parameters. - - sizes is specified as a sequence -- one item for each - input parameter. The item should be a Type Object that - corresponds to the input that will be used, or it should - be an integer specifying the maximum length of a string - parameter. If the item is None, then no predefined memory - area will be reserved for that column (this is useful to - avoid predefined areas for large inputs). - - This method would be used before the .execute*() method - is invoked. - - Implementations are free to have this method do nothing - and users are free to not use it. - - .setoutputsize(size[,column]) - - Set a column buffer size for fetches of large columns - (e.g. LONGs, BLOBs, etc.). The column is specified as an - index into the result sequence. Not specifying the column - will set the default size for all large columns in the - cursor. - - This method would be used before the .execute*() method - is invoked. - - Implementations are free to have this method do nothing - and users are free to not use it. - +.. _Error: -Type Objects and Constructors +`Error`_ + Exception that is the base class of all other error + exceptions. You can use this to catch all errors with one single + ``except`` statement. Warnings are not considered errors and thus + should not use this class as base. It must be a subclass of the + Python ``StandardError`` (defined in the module exceptions). - Many databases need to have the input in a particular format for - binding to an operation's input parameters. For example, if an - input is destined for a DATE column, then it must be bound to the - database in a particular string format. Similar problems exist - for "Row ID" columns or large binary items (e.g. blobs or RAW - columns). This presents problems for Python since the parameters - to the .execute*() method are untyped. When the database module - sees a Python string object, it doesn't know if it should be bound - as a simple CHAR column, as a raw BINARY item, or as a DATE. - To overcome this problem, a module must provide the constructors - defined below to create objects that can hold special values. - When passed to the cursor methods, the module can then detect the - proper type of the input parameter and bind it accordingly. +.. _InterfaceError: - A Cursor Object's description attribute returns information about - each of the result columns of a query. The type_code must compare - equal to one of Type Objects defined below. Type Objects may be - equal to more than one type code (e.g. DATETIME could be equal to - the type codes for date, time and timestamp columns; see the - Implementation Hints below for details). +`InterfaceError`_ + Exception raised for errors that are related to the database + interface rather than the database itself. It must be a subclass + of Error_. - The module exports the following constructors and singletons: - - Date(year,month,day) - This function constructs an object holding a date value. - - Time(hour,minute,second) +.. _DatabaseError: - This function constructs an object holding a time value. - - Timestamp(year,month,day,hour,minute,second) +`DatabaseError`_ + Exception raised for errors that are related to the database. It + must be a subclass of Error_. - This function constructs an object holding a time stamp - value. - DateFromTicks(ticks) +.. _DataError: - This function constructs an object holding a date value - from the given ticks value (number of seconds since the - epoch; see the documentation of the standard Python time - module for details). +`DataError`_ + Exception raised for errors that are due to problems with the + processed data like division by zero, numeric value out of range, + etc. It must be a subclass of DatabaseError_. - TimeFromTicks(ticks) - - This function constructs an object holding a time value - from the given ticks value (number of seconds since the - epoch; see the documentation of the standard Python time - module for details). - - TimestampFromTicks(ticks) - This function constructs an object holding a time stamp - value from the given ticks value (number of seconds since - the epoch; see the documentation of the standard Python - time module for details). +.. _OperationalError: - Binary(string) - - This function constructs an object capable of holding a - binary (long) string value. - +`OperationalError`_ + Exception raised for errors that are related to the database's + operation and not necessarily under the control of the programmer, + e.g. an unexpected disconnect occurs, the data source name is not + found, a transaction could not be processed, a memory allocation + error occurred during processing, etc. It must be a subclass of + DatabaseError_. - STRING - This type object is used to describe columns in a database - that are string-based (e.g. CHAR). +.. _IntegrityError: - BINARY +`IntegrityError`_ + Exception raised when the relational integrity of the database is + affected, e.g. a foreign key check fails. It must be a subclass + of DatabaseError_. - This type object is used to describe (long) binary columns - in a database (e.g. LONG, RAW, BLOBs). - - NUMBER - This type object is used to describe numeric columns in a - database. +.. _InternalError: - DATETIME - - This type object is used to describe date/time columns in - a database. - - ROWID - - This type object is used to describe the "Row ID" column - in a database. - - SQL NULL values are represented by the Python None singleton on - input and output. +`InternalError`_ + Exception raised when the database encounters an internal error, + e.g. the cursor is not valid anymore, the transaction is out of + sync, etc. It must be a subclass of DatabaseError_. - Note: Usage of Unix ticks for database interfacing can cause - troubles because of the limited date range they cover. +.. _ProgrammingError: -Implementation Hints for Module Authors +`ProgrammingError`_ + Exception raised for programming errors, e.g. table not found or + already exists, syntax error in the SQL statement, wrong number of + parameters specified, etc. It must be a subclass of + DatabaseError_. - * Date/time objects can be implemented as Python datetime module - objects (available since Python 2.3, with a C API since 2.4) or - using the mxDateTime package (available for all Python versions - since 1.5.2). They both provide all necessary constructors and - methods at Python and C level. - - * Here is a sample implementation of the Unix ticks based - constructors for date/time delegating work to the generic - constructors: + +.. _NotSupportedError: + +`NotSupportedError`_ + Exception raised in case a method or database API was used which + is not supported by the database, e.g. requesting a + `.rollback()`_ on a connection that does not support transaction + or has transactions turned off. It must be a subclass of + DatabaseError_. + +This is the exception inheritance layout:: + + StandardError + |__Warning + |__Error + |__InterfaceError + |__DatabaseError + |__DataError + |__OperationalError + |__IntegrityError + |__InternalError + |__ProgrammingError + |__NotSupportedError + +.. Note:: + The values of these exceptions are not defined. They should give the user + a fairly good idea of what went wrong, though. + + +.. _Connection: + +`Connection Objects`_ +===================== + +Connection objects should respond to the following methods. + + +`Connection methods`_ +--------------------- + +.. .close(): +.. _Connection.close: + +`.close() <#Connection.close>`_ + Close the connection now (rather than whenever ``.__del__()`` is + called). + + The connection will be unusable from this point forward; an Error_ + (or subclass) exception will be raised if any operation is + attempted with the connection. The same applies to all cursor + objects trying to use the connection. Note that closing a + connection without committing the changes first will cause an + implicit rollback to be performed. + + +.. _.commit: +.. _.commit(): + +`.commit`_\ () + Commit any pending transaction to the database. + + Note that if the database supports an auto-commit feature, this must be + initially off. An interface method may be provided to turn it back on. + + Database modules that do not support transactions should implement this + method with void functionality. + + +.. _.rollback: +.. _.rollback(): + +`.rollback`_\ () + This method is optional since not all databases provide transaction + support. [3]_ + + In case a database does provide transactions this method causes the + database to roll back to the start of any pending transaction. Closing a + connection without committing the changes first will cause an implicit + rollback to be performed. + + +.. _.cursor: + +`.cursor`_\ () + Return a new Cursor_ Object using the connection. + + If the database does not provide a direct cursor concept, the module will + have to emulate cursors using other means to the extent needed by this + specification. [4]_ + + + +.. _Cursor: + +`Cursor Objects`_ +================= + +These objects represent a database cursor, which is used to manage the +context of a fetch operation. Cursors created from the same connection +are not isolated, *i.e.*, any changes done to the database by a cursor +are immediately visible by the other cursors. Cursors created from +different connections can or can not be isolated, depending on how the +transaction support is implemented (see also the connection's +`.rollback`_\ () and `.commit`_\ () methods). + +Cursor Objects should respond to the following methods and attributes. + + +`Cursor attributes`_ +-------------------- + +.. _.description: + +`.description`_ + This read-only attribute is a sequence of 7-item sequences. + + Each of these sequences contains information describing one result + column: + + * ``name`` + * ``type_code`` + * ``display_size`` + * ``internal_size`` + * ``precision`` + * ``scale`` + * ``null_ok`` + + The first two items (``name`` and ``type_code``) are mandatory, + the other five are optional and are set to ``None`` if no + meaningful values can be provided. + + This attribute will be ``None`` for operations that do not return + rows or if the cursor has not had an operation invoked via the + `.execute*()`_ method yet. + + The ``type_code`` can be interpreted by comparing it to the `Type + Objects`_ specified in the section below. + + +.. _.rowcount: + +`.rowcount`_ + This read-only attribute specifies the number of rows that the last + `.execute*()`_ produced (for DQL statements like ``SELECT``) or affected + (for DML statements like ``UPDATE`` or ``INSERT``). [9]_ + + The attribute is -1 in case no `.execute*()`_ has been performed + on the cursor or the rowcount of the last operation is cannot be + determined by the interface. [7]_ + + .. note:: + Future versions of the DB API specification could redefine the + latter case to have the object return ``None`` instead of -1. + + +`Cursor methods`_ +----------------- + +.. _.callproc: +.. _.callproc(): + +`.callproc`_\ ( *procname* [, *parameters* ] ) + (This method is optional since not all databases provide stored + procedures. [3]_) + + Call a stored database procedure with the given name. The sequence + of parameters must contain one entry for each argument that the + procedure expects. The result of the call is returned as modified + copy of the input sequence. Input parameters are left untouched, + output and input/output parameters replaced with possibly new + values. + + The procedure may also provide a result set as output. This must + then be made available through the standard `.fetch*()`_ methods. + + +.. .close: +.. _Cursor.close: +.. _Cursor.close(): + +`.close <#Cursor.close>`_\ () + Close the cursor now (rather than whenever ``__del__`` is called). + + The cursor will be unusable from this point forward; an Error_ (or + subclass) exception will be raised if any operation is attempted + with the cursor. + + +.. _.execute*: +.. _.execute*(): + +.. _.execute: +.. _.execute(): + +`.execute`_\ (*operation* [, *parameters*]) + Prepare and execute a database operation (query or command). + + Parameters may be provided as sequence or mapping and will be + bound to variables in the operation. Variables are specified in a + database-specific notation (see the module's paramstyle_ attribute + for details). [5]_ + + A reference to the operation will be retained by the cursor. If + the same operation object is passed in again, then the cursor can + optimize its behavior. This is most effective for algorithms + where the same operation is used, but different parameters are + bound to it (many times). + + For maximum efficiency when reusing an operation, it is best to + use the `.setinputsizes()`_ method to specify the parameter types + and sizes ahead of time. It is legal for a parameter to not match + the predefined information; the implementation should compensate, + possibly with a loss of efficiency. + + The parameters may also be specified as list of tuples to + e.g. insert multiple rows in a single operation, but this kind of + usage is deprecated: `.executemany()`_ should be used instead. + + Return values are not defined. + + +.. _.executemany: +.. _.executemany(): + +`.executemany`_\ ( *operation*, *seq_of_parameters* ) + Prepare a database operation (query or command) and then execute it + against all parameter sequences or mappings found in the sequence + *seq_of_parameters*. + + Modules are free to implement this method using multiple calls to + the `.execute()`_ method or by using array operations to have the + database process the sequence as a whole in one call. + + Use of this method for an operation which produces one or more + result sets constitutes undefined behavior, and the implementation + is permitted (but not required) to raise an exception when it + detects that a result set has been created by an invocation of the + operation. + + The same comments as for `.execute()`_ also apply accordingly to + this method. + + Return values are not defined. + + +.. _.fetch*: +.. _.fetch*(): + +.. _.fetchone: +.. _.fetchone(): + +`.fetchone`_\ () + Fetch the next row of a query result set, returning a single + sequence, or ``None`` when no more data is available. [6]_ + + An Error_ (or subclass) exception is raised if the previous call + to `.execute*()`_ did not produce any result set or no call was + issued yet. + + +.. _.fetchmany: +.. _.fetchmany(): + +`.fetchmany`_\ ([*size=cursor.arraysize*]) + Fetch the next set of rows of a query result, returning a sequence + of sequences (e.g. a list of tuples). An empty sequence is + returned when no more rows are available. + + The number of rows to fetch per call is specified by the + parameter. If it is not given, the cursor's arraysize determines + the number of rows to be fetched. The method should try to fetch + as many rows as indicated by the size parameter. If this is not + possible due to the specified number of rows not being available, + fewer rows may be returned. + + An Error_ (or subclass) exception is raised if the previous call + to `.execute*()`_ did not produce any result set or no call was + issued yet. + + Note there are performance considerations involved with the *size* + parameter. For optimal performance, it is usually best to use the + `.arraysize`_ attribute. If the size parameter is used, then it + is best for it to retain the same value from one `.fetchmany()`_ + call to the next. + + +.. _.fetchall: +.. _.fetchall(): + +`.fetchall`_\ () + Fetch all (remaining) rows of a query result, returning them as a + sequence of sequences (e.g. a list of tuples). Note that the + cursor's arraysize attribute can affect the performance of this + operation. + + An Error_ (or subclass) exception is raised if the previous call + to `.execute*()`_ did not produce any result set or no call was + issued yet. + + +.. _.nextset: +.. _.nextset(): + +`.nextset`_\ () + (This method is optional since not all databases support multiple + result sets. [3]_) + + This method will make the cursor skip to the next available set, + discarding any remaining rows from the current set. + + If there are no more sets, the method returns ``None``. Otherwise, + it returns a true value and subsequent calls to the `.fetch*()`_ + methods will return rows from the next result set. + + An Error_ (or subclass) exception is raised if the previous call + to `.execute*()`_ did not produce any result set or no call was + issued yet. + + +.. _.arraysize: + +`.arraysize`_ + This read/write attribute specifies the number of rows to fetch at + a time with `.fetchmany()`_. It defaults to 1 meaning to fetch a + single row at a time. + + Implementations must observe this value with respect to the + `.fetchmany()`_ method, but are free to interact with the database + a single row at a time. It may also be used in the implementation + of `.executemany()`_. + + +.. _.setinputsizes: +.. _.setinputsizes(): + +`.setinputsizes`_\ (*sizes*) + This can be used before a call to `.execute*()`_ to predefine + memory areas for the operation's parameters. + + *sizes* is specified as a sequence ? one item for each input + parameter. The item should be a Type Object that corresponds to + the input that will be used, or it should be an integer specifying + the maximum length of a string parameter. If the item is + ``None``, then no predefined memory area will be reserved for that + column (this is useful to avoid predefined areas for large + inputs). + + This method would be used before the `.execute*()`_ method is + invoked. + + Implementations are free to have this method do nothing and users + are free to not use it. + + +.. _.setoutputsize: +.. _.setoutputsize(): + +`.setoutputsize`_\ (*size* [, *column*]) + Set a column buffer size for fetches of large columns + (e.g. ``LONG``\s, ``BLOB``\s, etc.). The column is specified as + an index into the result sequence. Not specifying the column will + set the default size for all large columns in the cursor. + + This method would be used before the `.execute*()`_ method is + invoked. + + Implementations are free to have this method do nothing and users + are free to not use it. + + +.. _Type Objects: + +`Type Objects and Constructors`_ +================================ + +Many databases need to have the input in a particular format for +binding to an operation's input parameters. For example, if an input +is destined for a ``DATE`` column, then it must be bound to the +database in a particular string format. Similar problems exist for +"Row ID" columns or large binary items (e.g. blobs or ``RAW`` +columns). This presents problems for Python since the parameters to +the `.execute*()`_ method are untyped. When the database module sees +a Python string object, it doesn't know if it should be bound as a +simple ``CHAR`` column, as a raw ``BINARY`` item, or as a ``DATE``. + +To overcome this problem, a module must provide the constructors +defined below to create objects that can hold special values. When +passed to the cursor methods, the module can then detect the proper +type of the input parameter and bind it accordingly. + +A Cursor_ Object's description attribute returns information about +each of the result columns of a query. The ``type_code`` must compare +equal to one of Type Objects defined below. Type Objects may be equal +to more than one type code (e.g. ``DATETIME`` could be equal to the +type codes for date, time and timestamp columns; see the +`Implementation Hints`_ below for details). + +The module exports the following constructors and singletons: + +.. _Date: + +`Date`_\ (*year*, *month*, *day*) + This function constructs an object holding a date value. + + +.. _Time: + +`Time`_\ (*hour*, *minute*, *second*) + This function constructs an object holding a time value. + + +.. _Timestamp: + +`Timestamp`_\ (*year*, *month*, *day*, *hour*, *minute*, *second*) + This function constructs an object holding a time stamp value. + + +.. _DateFromTicks: + +`DateFromTicks`_\ (*ticks*) + This function constructs an object holding a date value from the + given ticks value (number of seconds since the epoch; see the + documentation of `the standard Python time module + `__ for details). + +.. _TimeFromTicks: + +`TimeFromTicks`_\ (*ticks*) + This function constructs an object holding a time value from the + given ticks value (number of seconds since the epoch; see the + documentation of the standard Python time module for details). + + +.. _TimeStampFromTicks: + +`TimestampFromTicks`_\ (*ticks*) + This function constructs an object holding a time stamp value from + the given ticks value (number of seconds since the epoch; see the + documentation of the standard Python time module for details). + + +.. _Binary: + +`Binary`_\ (*string*) + This function constructs an object capable of holding a binary + (long) string value. + + +.. _STRING: + +`STRING`_ type + This type object is used to describe columns in a database that + are string-based (e.g. ``CHAR``). + + +.. _Binary type: + +`BINARY`_ type + This type object is used to describe (long) binary columns in a + database (e.g. ``LONG``, ``RAW``, ``BLOB``\s). + + +.. _NUMBER: + +`NUMBER`_ type + This type object is used to describe numeric columns in a + database. + + +.. _DATETIME: + +`DATETIME`_ type + This type object is used to describe date/time columns in a + database. + +.. _ROWID: + +`ROWID`_ type + This type object is used to describe the "Row ID" column in a + database. + + +SQL ``NULL`` values are represented by the Python ``None`` singleton +on input and output. + +.. Note:: + Usage of Unix ticks for database interfacing can cause troubles + because of the limited date range they cover. + + + +.. _Implementation Hints: + +`Implementation Hints for Module Authors`_ +========================================== + +* Date/time objects can be implemented as `Python datetime module + `__ objects (available + since Python 2.3, with a C API since 2.4) or using the `mxDateTime + `_ package + (available for all Python versions since 1.5.2). They both provide + all necessary constructors and methods at Python and C level. + +* Here is a sample implementation of the Unix ticks based constructors + for date/time delegating work to the generic constructors:: import time @@ -599,17 +706,15 @@ def TimestampFromTicks(ticks): return Timestamp(*time.localtime(ticks)[:6]) - * The preferred object type for Binary objects are the - buffer types available in standard Python starting with - version 1.5.2. Please see the Python documentation for - details. For information about the C interface have a - look at Include/bufferobject.h and - Objects/bufferobject.c in the Python source - distribution. +* The preferred object type for Binary objects are the buffer types + available in standard Python starting with version 1.5.2. Please + see the Python documentation for details. For information about the + C interface have a look at ``Include/bufferobject.h`` and + ``Objects/bufferobject.c`` in the Python source distribution. - * This Python class allows implementing the above type - objects even though the description type code field yields - multiple values for on type object: +* This Python class allows implementing the above type objects even + though the description type code field yields multiple values for on + type object:: class DBAPITypeObject: def __init__(self,*values): @@ -622,11 +727,11 @@ else: return -1 - The resulting type object compares equal to all values - passed to the constructor. + The resulting type object compares equal to all values passed to the + constructor. - * Here is a snippet of Python code that implements the exception - hierarchy defined above: +* Here is a snippet of Python code that implements the exception + hierarchy defined above:: import exceptions @@ -659,490 +764,555 @@ class NotSupportedError(DatabaseError): pass - - In C you can use the PyErr_NewException(fullname, - base, NULL) API to create the exception objects. + In C you can use the ``PyErr_NewException(fullname, base, NULL)`` + API to create the exception objects. -Optional DB API Extensions - During the lifetime of DB API 2.0, module authors have often - extended their implementations beyond what is required by this DB - API specification. To enhance compatibility and to provide a clean - upgrade path to possible future versions of the specification, - this section defines a set of common extensions to the core DB API - 2.0 specification. +`Optional DB API Extensions`_ +============================= - As with all DB API optional features, the database module authors - are free to not implement these additional attributes and methods - (using them will then result in an AttributeError) or to raise a - NotSupportedError in case the availability can only be checked at - run-time. +During the lifetime of DB API 2.0, module authors have often extended +their implementations beyond what is required by this DB API +specification. To enhance compatibility and to provide a clean upgrade +path to possible future versions of the specification, this section +defines a set of common extensions to the core DB API 2.0 +specification. - It has been proposed to make usage of these extensions optionally - visible to the programmer by issuing Python warnings through the - Python warning framework. To make this feature useful, the warning - messages must be standardized in order to be able to mask - them. These standard messages are referred to below as "Warning - Message". +As with all DB API optional features, the database module authors are +free to not implement these additional attributes and methods (using +them will then result in an ``AttributeError``) or to raise a +NotSupportedError_ in case the availability can only be checked at +run-time. - Cursor Attribute .rownumber +It has been proposed to make usage of these extensions optionally +visible to the programmer by issuing Python warnings through the +Python warning framework. To make this feature useful, the warning +messages must be standardized in order to be able to mask them. These +standard messages are referred to below as *Warning Message*. - This read-only attribute should provide the current 0-based - index of the cursor in the result set or None if the index - cannot be determined. - The index can be seen as index of the cursor in a sequence - (the result set). The next fetch operation will fetch the row - indexed by .rownumber in that sequence. +.. _.rownumber: - Warning Message: "DB-API extension cursor.rownumber used" +Cursor\ `.rownumber`_ + This read-only attribute should provide the current 0-based index + of the cursor in the result set or ``None`` if the index cannot be + determined. - Connection Attributes .Error, .ProgrammingError, etc. + The index can be seen as index of the cursor in a sequence (the + result set). The next fetch operation will fetch the row indexed + by `.rownumber`_ in that sequence. - All exception classes defined by the DB API standard should be - exposed on the Connection objects as attributes (in addition - to being available at module scope). + *Warning Message:* "DB-API extension cursor.rownumber used" - These attributes simplify error handling in multi-connection - environments. - Warning Message: "DB-API extension connection. used" +.. _Connection.Error: +.. _Connection.ProgrammingError: - Cursor Attributes .connection +`Connection.Error`_, `Connection.ProgrammingError`_, etc. + All exception classes defined by the DB API standard should be + exposed on the Connection_ objects as attributes (in addition to + being available at module scope). - This read-only attribute return a reference to the Connection - object on which the cursor was created. + These attributes simplify error handling in multi-connection + environments. - The attribute simplifies writing polymorph code in - multi-connection environments. + *Warning Message:* "DB-API extension connection. used" - Warning Message: "DB-API extension cursor.connection used" - Cursor Method .scroll(value[,mode='relative']) +.. _.connection: - Scroll the cursor in the result set to a new position according - to mode. +Cursor\ `.connection`_ + This read-only attribute return a reference to the Connection_ + object on which the cursor was created. - If mode is 'relative' (default), value is taken as offset to - the current position in the result set, if set to 'absolute', - value states an absolute target position. + The attribute simplifies writing polymorph code in + multi-connection environments. - An IndexError should be raised in case a scroll operation would - leave the result set. In this case, the cursor position is left - undefined (ideal would be to not move the cursor at all). + *Warning Message:* "DB-API extension cursor.connection used" - Note: This method should use native scrollable cursors, if - available , or revert to an emulation for forward-only - scrollable cursors. The method may raise NotSupportedErrors to - signal that a specific operation is not supported by the - database (e.g. backward scrolling). - Warning Message: "DB-API extension cursor.scroll() used" +.. _.scroll: +.. _.scroll(): - Cursor Attribute .messages +Cursor\ `.scroll`_\ (*value* [, *mode='relative'* ]) + Scroll the cursor in the result set to a new position according to + *mode*. - This is a Python list object to which the interface appends - tuples (exception class, exception value) for all messages - which the interfaces receives from the underlying database for - this cursor. + If mode is ``relative`` (default), value is taken as offset to the + current position in the result set, if set to ``absolute``, value + states an absolute target position. - The list is cleared by all standard cursor methods calls (prior - to executing the call) except for the .fetch*() calls - automatically to avoid excessive memory usage and can also be - cleared by executing "del cursor.messages[:]". + An ``IndexError`` should be raised in case a scroll operation + would leave the result set. In this case, the cursor position is + left undefined (ideal would be to not move the cursor at all). - All error and warning messages generated by the database are - placed into this list, so checking the list allows the user to - verify correct operation of the method calls. + .. Note:: + This method should use native scrollable cursors, if available + , or revert to an emulation for forward-only scrollable + cursors. The method may raise NotSupportedError_ to signal + that a specific operation is not supported by the database + (e.g. backward scrolling). - The aim of this attribute is to eliminate the need for a - Warning exception which often causes problems (some warnings - really only have informational character). + *Warning Message:* "DB-API extension cursor.scroll() used" - Warning Message: "DB-API extension cursor.messages used" - Connection Attribute .messages +.. _Cursor.messages: - Same as cursor.messages except that the messages in the list - are connection oriented. +`Cursor.messages`_ + This is a Python list object to which the interface appends tuples + (exception class, exception value) for all messages which the + interfaces receives from the underlying database for this cursor. - The list is cleared automatically by all standard connection - methods calls (prior to executing the call) to avoid excessive - memory usage and can also be cleared by executing "del - connection.messages[:]". + The list is cleared by all standard cursor methods calls (prior to + executing the call) except for the `.fetch*()`_ calls + automatically to avoid excessive memory usage and can also be + cleared by executing ``del cursor.messages[:]``. - Warning Message: "DB-API extension connection.messages used" + All error and warning messages generated by the database are + placed into this list, so checking the list allows the user to + verify correct operation of the method calls. - Cursor Method .next() - - Return the next row from the currently executing SQL statement - using the same semantics as .fetchone(). A StopIteration - exception is raised when the result set is exhausted for Python - versions 2.2 and later. Previous versions don't have the - StopIteration exception and so the method should raise an - IndexError instead. + The aim of this attribute is to eliminate the need for a Warning + exception which often causes problems (some warnings really only + have informational character). - Warning Message: "DB-API extension cursor.next() used" + *Warning Message:* "DB-API extension cursor.messages used" - Cursor Method .__iter__() - Return self to make cursors compatible to the iteration - protocol [8]. +.. _Connection.messages: - Warning Message: "DB-API extension cursor.__iter__() used" +`Connection.messages`_ + Same as Cursor.messages_ except that the messages in the list are + connection oriented. - Cursor Attribute .lastrowid + The list is cleared automatically by all standard connection + methods calls (prior to executing the call) to avoid excessive + memory usage and can also be cleared by executing ``del + connection.messages[:]``. - This read-only attribute provides the rowid of the last - modified row (most databases return a rowid only when a single - INSERT operation is performed). If the operation does not set - a rowid or if the database does not support rowids, this - attribute should be set to None. + *Warning Message:* "DB-API extension connection.messages used" - The semantics of .lastrowid are undefined in case the last - executed statement modified more than one row, e.g. when - using INSERT with .executemany(). - Warning Message: "DB-API extension cursor.lastrowid used" +.. _.next: +.. _.next(): - -Optional Error Handling Extensions +Cursor\ `.next`_\ () + Return the next row from the currently executing SQL statement + using the same semantics as `.fetchone()`_. A ``StopIteration`` + exception is raised when the result set is exhausted for Python + versions 2.2 and later. Previous versions don't have the + ``StopIteration`` exception and so the method should raise an + ``IndexError`` instead. - The core DB API specification only introduces a set of exceptions - which can be raised to report errors to the user. In some cases, - exceptions may be too disruptive for the flow of a program or even - render execution impossible. + *Warning Message:* "DB-API extension cursor.next() used" - For these cases and in order to simplify error handling when - dealing with databases, database module authors may choose to - implement user defineable error handlers. This section describes a - standard way of defining these error handlers. - Cursor/Connection Attribute .errorhandler +.. _.__iter__: +.. _.__iter__(): - Read/write attribute which references an error handler to call - in case an error condition is met. +Cursor\ `.__iter__`_\ () + Return self to make cursors compatible to the iteration protocol + [8]_. - The handler must be a Python callable taking the following - arguments: + *Warning Message:* "DB-API extension cursor.__iter__() used" - errorhandler(connection, cursor, errorclass, errorvalue) - where connection is a reference to the connection on which the - cursor operates, cursor a reference to the cursor (or None in - case the error does not apply to a cursor), errorclass is an - error class which to instantiate using errorvalue as - construction argument. +.. _.lastrowid: - The standard error handler should add the error information to - the appropriate .messages attribute (connection.messages or - cursor.messages) and raise the exception defined by the given - errorclass and errorvalue parameters. +Cursor\ `.lastrowid`_ + This read-only attribute provides the rowid of the last modified + row (most databases return a rowid only when a single ``INSERT`` + operation is performed). If the operation does not set a rowid or + if the database does not support rowids, this attribute should be + set to ``None``. - If no errorhandler is set (the attribute is None), the - standard error handling scheme as outlined above, should be - applied. + The semantics of ``.lastrowid`` are undefined in case the last + executed statement modified more than one row, e.g. when using + ``INSERT`` with ``.executemany()``. - Warning Message: "DB-API extension .errorhandler used" + *Warning Message:* "DB-API extension cursor.lastrowid used" - Cursors should inherit the .errorhandler setting from their - connection objects at cursor creation time. +`Optional Error Handling Extensions`_ +===================================== -Optional Two-Phase Commit Extensions +The core DB API specification only introduces a set of exceptions +which can be raised to report errors to the user. In some cases, +exceptions may be too disruptive for the flow of a program or even +render execution impossible. - Many databases have support for two-phase commit (TPC) which - allows managing transactions across multiple database connections - and other resources. +For these cases and in order to simplify error handling when dealing +with databases, database module authors may choose to implement user +defineable error handlers. This section describes a standard way of +defining these error handlers. - If a database backend provides support for two-phase commit and - the database module author wishes to expose this support, the - following API should be implemented. NotSupportedError should be - raised, if the database backend support for two-phase commit - can only be checked at run-time. +.. _Connection.errorhandler: +.. _Cursor.errorhandler: - TPC Transaction IDs +`Connection.errorhandler`_, `Cursor.errorhandler`_ + Read/write attribute which references an error handler to call in + case an error condition is met. - As many databases follow the XA specification, transaction IDs - are formed from three components: - - * a format ID - * a global transaction ID - * a branch qualifier + The handler must be a Python callable taking the following arguments: - For a particular global transaction, the first two components - should be the same for all resources. Each resource in the - global transaction should be assigned a different branch - qualifier. + .. parsed-literal:: - The various components must satisfy the following criteria: - - * format ID: a non-negative 32-bit integer. - - * global transaction ID and branch qualifier: byte strings no - longer than 64 characters. + errorhandler(*connection*, *cursor*, *errorclass*, *errorvalue*) - Transaction IDs are created with the .xid() connection method: + where connection is a reference to the connection on which the + cursor operates, cursor a reference to the cursor (or ``None`` in + case the error does not apply to a cursor), *errorclass* is an + error class which to instantiate using *errorvalue* as + construction argument. - .xid(format_id, global_transaction_id, branch_qualifier) + The standard error handler should add the error information to the + appropriate ``.messages`` attribute (`Connection.messages`_ or + `Cursor.messages`_) and raise the exception defined by the given + *errorclass* and *errorvalue* parameters. - Returns a transaction ID object suitable for passing to the - .tpc_*() methods of this connection. + If no ``.errorhandler`` is set (the attribute is ``None``), the + standard error handling scheme as outlined above, should be + applied. - If the database connection does not support TPC, a - NotSupportedError is raised. + *Warning Message:* "DB-API extension .errorhandler used" - The type of the object returned by .xid() is not defined, but - it must provide sequence behaviour, allowing access to the - three components. A conforming database module could choose - to represent transaction IDs with tuples rather than a custom - object. +Cursors should inherit the ``.errorhandler`` setting from their +connection objects at cursor creation time. - TPC Connection Methods - .tpc_begin(xid) +`Optional Two-Phase Commit Extensions`_ +======================================= - Begins a TPC transaction with the given transaction ID xid. +Many databases have support for two-phase commit (TPC) which allows +managing transactions across multiple database connections and other +resources. - This method should be called outside of a transaction - (i.e. nothing may have executed since the last .commit() or - .rollback()). +If a database backend provides support for two-phase commit and the +database module author wishes to expose this support, the following +API should be implemented. NotSupportedError_ should be raised, if the +database backend support for two-phase commit can only be checked at +run-time. - Furthermore, it is an error to call .commit() or .rollback() - within the TPC transaction. A ProgrammingError is raised, if - the application calls .commit() or .rollback() during an - active TPC transaction. +`TPC Transaction IDs`_ +---------------------- - If the database connection does not support TPC, a - NotSupportedError is raised. +As many databases follow the XA specification, transaction IDs are +formed from three components: - .tpc_prepare() +* a format ID +* a global transaction ID +* a branch qualifier - Performs the first phase of a transaction started with - .tpc_begin(). A ProgrammingError should be raised if this - method outside of a TPC transaction. +For a particular global transaction, the first two components should +be the same for all resources. Each resource in the global +transaction should be assigned a different branch qualifier. - After calling .tpc_prepare(), no statements can be executed - until tpc_commit() or tpc_rollback() have been called. +The various components must satisfy the following criteria: - .tpc_commit([xid]) +* format ID: a non-negative 32-bit integer. - When called with no arguments, .tpc_commit() commits a TPC - transaction previously prepared with .tpc_prepare(). +* global transaction ID and branch qualifier: byte strings no + longer than 64 characters. - If .tpc_commit() is called prior to .tpc_prepare(), a single - phase commit is performed. A transaction manager may choose - to do this if only a single resource is participating in the - global transaction. +Transaction IDs are created with the `.xid()`_ Connection method: - When called with a transaction ID xid, the database commits - the given transaction. If an invalid transaction ID is - provided, a ProgrammingError will be raised. This form should - be called outside of a transaction, and is intended for use in - recovery. - On return, the TPC transaction is ended. +.. _.xid: +.. _.xid(): - .tpc_rollback([xid]) +`.xid`_\ (*format_id*, *global_transaction_id*, *branch_qualifier*) + Returns a transaction ID object suitable for passing to the + `.tpc_*()`_ methods of this connection. - When called with no arguments, .tpc_rollback() rolls back a - TPC transaction. It may be called before or after - .tpc_prepare(). + If the database connection does not support TPC, a + NotSupportedError_ is raised. - When called with a transaction ID xid, it rolls back the given - transaction. If an invalid transaction ID is provided, a - ProgrammingError is raised. This form should be called - outside of a transaction, and is intended for use in recovery. + The type of the object returned by `.xid()`_ is not defined, but + it must provide sequence behaviour, allowing access to the three + components. A conforming database module could choose to + represent transaction IDs with tuples rather than a custom object. - On return, the TPC transaction is ended. - .tpc_recover() +`TPC Connection Methods`_ +------------------------- - Returns a list of pending transaction IDs suitable for use - with .tpc_commit(xid) or .tpc_rollback(xid). +.. _.tpc_*: +.. _.tpc_*(): - If the database does not support transaction recovery, it may - return an empty list or raise NotSupportedError. +.. _.tpc_begin: +.. _.tpc_begin(): +`.tpc_begin`_\ (*xid*) + Begins a TPC transaction with the given transaction ID *xid*. -Frequently Asked Questions + This method should be called outside of a transaction (*i.e.* + nothing may have executed since the last `.commit()`_ or + `.rollback()`_). - The database SIG often sees reoccurring questions about the DB API - specification. This section covers some of the issues people - sometimes have with the specification. + Furthermore, it is an error to call `.commit()`_ or `.rollback()`_ + within the TPC transaction. A ProgrammingError_ is raised, if the + application calls `.commit()`_ or `.rollback()`_ during an active + TPC transaction. - Question: + If the database connection does not support TPC, a + NotSupportedError_ is raised. - How can I construct a dictionary out of the tuples returned by - .fetch*(): - Answer: +.. _.tpc_prepare: +.. _.tpc_prepare(): - There are several existing tools available which provide - helpers for this task. Most of them use the approach of using - the column names defined in the cursor attribute .description - as basis for the keys in the row dictionary. +`.tpc_prepare`_\ () + Performs the first phase of a transaction started with + `.tpc_begin()`_. A ProgrammingError_ should be raised if this + method outside of a TPC transaction. - Note that the reason for not extending the DB API specification - to also support dictionary return values for the .fetch*() - methods is that this approach has several drawbacks: + After calling `.tpc_prepare()`_, no statements can be executed + until `.tpc_commit()`_ or `.tpc_rollback()`_ have been called. - * Some databases don't support case-sensitive column names or - auto-convert them to all lowercase or all uppercase - characters. - - * Columns in the result set which are generated by the query - (e.g. using SQL functions) don't map to table column names - and databases usually generate names for these columns in a - very database specific way. - As a result, accessing the columns through dictionary keys - varies between databases and makes writing portable code - impossible. +.. _.tpc_commit: +.. _.tpc_commit(): +`.tpc_commit`_\ ([ *xid* ]) + When called with no arguments, `.tpc_commit()`_ commits a TPC + transaction previously prepared with `.tpc_prepare()`_. -Major Changes from Version 1.0 to Version 2.0 + If `.tpc_commit()`_ is called prior to `.tpc_prepare()`_, a single + phase commit is performed. A transaction manager may choose to do + this if only a single resource is participating in the global + transaction. - The Python Database API 2.0 introduces a few major changes - compared to the 1.0 version. Because some of these changes will - cause existing DB API 1.0 based scripts to break, the major - version number was adjusted to reflect this change. - - These are the most important changes from 1.0 to 2.0: - - * The need for a separate dbi module was dropped and the - functionality merged into the module interface itself. + When called with a transaction ID *xid*, the database commits the + given transaction. If an invalid transaction ID is provided, a + ProgrammingError_ will be raised. This form should be called + outside of a transaction, and is intended for use in recovery. - * New constructors and Type Objects were added for date/time - values, the RAW Type Object was renamed to BINARY. The - resulting set should cover all basic data types commonly - found in modern SQL databases. + On return, the TPC transaction is ended. - * New constants (apilevel, threadlevel, paramstyle) and - methods (.executemany(), .nextset()) were added to provide - better database bindings. - - * The semantics of .callproc() needed to call stored - procedures are now clearly defined. - - * The definition of the .execute() return value changed. - Previously, the return value was based on the SQL statement - type (which was hard to implement right) -- it is undefined - now; use the more flexible .rowcount attribute - instead. Modules are free to return the old style return - values, but these are no longer mandated by the - specification and should be considered database interface - dependent. - - * Class based exceptions were incorporated into the - specification. Module implementors are free to extend the - exception layout defined in this specification by - subclassing the defined exception classes. - Post-publishing additions to the DB API 2.0 specification: +.. _.tpc_rollback: +.. _.tpc_rollback(): - * Additional optional DB API extensions to the set of - core functionality were specified. +`.tpc_rollback`_\ ([ *xid* ]) + When called with no arguments, `.tpc_rollback()`_ rolls back a TPC + transaction. It may be called before or after `.tpc_prepare()`_. + When called with a transaction ID *xid*, it rolls back the given + transaction. If an invalid transaction ID is provided, a + ProgrammingError_ is raised. This form should be called outside + of a transaction, and is intended for use in recovery. -Open Issues + On return, the TPC transaction is ended. - Although the version 2.0 specification clarifies a lot of - questions that were left open in the 1.0 version, there are still - some remaining issues which should be addressed in future - versions: - - * Define a useful return value for .nextset() for the case where - a new result set is available. - - * Integrate the decimal module Decimal object for use as - loss-less monetary and decimal interchange format. +.. _.tpc_recover: +.. _.tpc_recover(): +`.tpc_recover`_\ () + Returns a list of pending transaction IDs suitable for use with + ``.tpc_commit(xid)`` or ``.tpc_rollback(xid)``. -Footnotes + If the database does not support transaction recovery, it may + return an empty list or raise NotSupportedError_. - [1] As a guideline the connection constructor parameters should be - implemented as keyword parameters for more intuitive use and - follow this order of parameters: - - dsn Data source name as string - user User name as string (optional) - password Password as string (optional) - host Hostname (optional) - database Database name (optional) - - E.g. a connect could look like this: - - connect(dsn='myhost:MYDB',user='guido',password='234$') - - [2] Module implementors should prefer 'numeric', 'named' or - 'pyformat' over the other formats because these offer more - clarity and flexibility. - [3] If the database does not support the functionality required - by the method, the interface should throw an exception in - case the method is used. - - The preferred approach is to not implement the method and - thus have Python generate an AttributeError in - case the method is requested. This allows the programmer to - check for database capabilities using the standard - hasattr() function. - - For some dynamically configured interfaces it may not be - appropriate to require dynamically making the method - available. These interfaces should then raise a - NotSupportedError to indicate the non-ability - to perform the roll back when the method is invoked. - - [4] a database interface may choose to support named cursors by - allowing a string argument to the method. This feature is - not part of the specification, since it complicates - semantics of the .fetch*() methods. - - [5] The module will use the __getitem__ method of the parameters - object to map either positions (integers) or names (strings) - to parameter values. This allows for both sequences and - mappings to be used as input. - - The term "bound" refers to the process of binding an input - value to a database execution buffer. In practical terms, - this means that the input value is directly used as a value - in the operation. The client should not be required to - "escape" the value so that it can be used -- the value - should be equal to the actual database value. - - [6] Note that the interface may implement row fetching using - arrays and other optimizations. It is not - guaranteed that a call to this method will only move the - associated cursor forward by one row. - - [7] The rowcount attribute may be coded in a way that updates - its value dynamically. This can be useful for databases that - return usable rowcount values only after the first call to - a .fetch*() method. - [8] Implementation Note: Python C extensions will have to - implement the tp_iter slot on the cursor object instead of the - .__iter__() method. +`Frequently Asked Questions`_ +============================= -Acknowledgements +The database SIG often sees reoccurring questions about the DB API +specification. This section covers some of the issues people sometimes +have with the specification. - Many thanks go to Andrew Kuchling who converted the Python - Database API Specification 2.0 from the original HTML format into - the PEP format. +**Question:** - Many thanks to James Henstridge for leading the discussion which - led to the standardization of the two-phase commit API extensions. +How can I construct a dictionary out of the tuples returned by +`.fetch*()`_: -Copyright +**Answer:** - This document has been placed in the Public Domain. +There are several existing tools available which provide helpers for +this task. Most of them use the approach of using the column names +defined in the cursor attribute `.description`_ as basis for the keys +in the row dictionary. +Note that the reason for not extending the DB API specification to +also support dictionary return values for the `.fetch*()`_ methods is +that this approach has several drawbacks: - -Local Variables: -mode: indented-text -indent-tabs-mode: nil -End: +* Some databases don't support case-sensitive column names or + auto-convert them to all lowercase or all uppercase characters. + +* Columns in the result set which are generated by the query (e.g. + using SQL functions) don't map to table column names and databases + usually generate names for these columns in a very database specific + way. + +As a result, accessing the columns through dictionary keys varies +between databases and makes writing portable code impossible. + + + +`Major Changes from Version 1.0 to Version 2.0`_ +================================================ + +The Python Database API 2.0 introduces a few major changes compared to +the 1.0 version. Because some of these changes will cause existing DB +API 1.0 based scripts to break, the major version number was adjusted +to reflect this change. + +These are the most important changes from 1.0 to 2.0: + +* The need for a separate dbi module was dropped and the functionality + merged into the module interface itself. + +* New constructors and `Type Objects`_ were added for date/time + values, the ``RAW`` Type Object was renamed to ``BINARY``. The + resulting set should cover all basic data types commonly found in + modern SQL databases. + +* New constants (apilevel_, threadsafety_, paramstyle_) and methods + (`.executemany()`_, `.nextset()`_) were added to provide better + database bindings. + +* The semantics of `.callproc()`_ needed to call stored procedures are + now clearly defined. + +* The definition of the `.execute()`_ return value changed. + Previously, the return value was based on the SQL statement type + (which was hard to implement right) ? it is undefined now; use the + more flexible `.rowcount`_ attribute instead. Modules are free to + return the old style return values, but these are no longer mandated + by the specification and should be considered database interface + dependent. + +* Class based exceptions_ were incorporated into the specification. + Module implementors are free to extend the exception layout defined + in this specification by subclassing the defined exception classes. + + +Post-publishing additions to the DB API 2.0 specification: + +* Additional optional DB API extensions to the set of core + functionality were specified. + + +`Open Issues`_ +============== + +Although the version 2.0 specification clarifies a lot of questions +that were left open in the 1.0 version, there are still some remaining +issues which should be addressed in future versions: + +* Define a useful return value for `.nextset()`_ for the case where a + new result set is available. + +* Integrate the `decimal module + `__ ``Decimal`` object + for use as loss-less monetary and decimal interchange format. + + + +`Footnotes`_ +============ + +.. [1] As a guideline the connection constructor parameters should be + implemented as keyword parameters for more intuitive use and + follow this order of parameters: + + ============= ==================================== + Parameter Meaning + ============= ==================================== + ``dsn`` Data source name as string + ``user`` User name as string (optional) + ``password`` Password as string (optional) + ``host`` Hostname (optional) + ``database`` Database name (optional) + ============= ==================================== + + E.g. a connect could look like this:: + + connect(dsn='myhost:MYDB', user='guido', password='234$') + +.. [2] Module implementors should prefer ``numeric``, ``named`` or + ``pyformat`` over the other formats because these offer more + clarity and flexibility. + + +.. [3] If the database does not support the functionality required by + the method, the interface should throw an exception in case the + method is used. + + The preferred approach is to not implement the method and thus + have Python generate an ``AttributeError`` in case the method is requested. This + allows the programmer to check for database capabilities using the + standard ``hasattr()`` function. + + For some dynamically configured interfaces it may not be + appropriate to require dynamically making the method + available. These interfaces should then raise a + ``NotSupportedError`` to indicate the non-ability to perform the + roll back when the method is invoked. + +.. [4] A database interface may choose to support named cursors by + allowing a string argument to the method. This feature is not part + of the specification, since it complicates semantics of the + `.fetch*()`_ methods. + +.. [5] The module will use the ``__getitem__`` method of the + parameters object to map either positions (integers) or names + (strings) to parameter values. This allows for both sequences and + mappings to be used as input. + + The term *bound* refers to the process of binding an input value + to a database execution buffer. In practical terms, this means + that the input value is directly used as a value in the operation. + The client should not be required to "escape" the value so that it + can be used ? the value should be equal to the actual database + value. + +.. [6] Note that the interface may implement row fetching using arrays + and other optimizations. It is not guaranteed that a call to this + method will only move the associated cursor forward by one row. + +.. [7] The ``rowcount`` attribute may be coded in a way that updates + its value dynamically. This can be useful for databases that + return usable ``rowcount`` values only after the first call to a + `.fetch*()`_ method. + +.. [8] Implementation Note: Python C extensions will have to implement + the ``tp_iter`` slot on the cursor object instead of the + ``.__iter__()`` method. + +.. [9] The term *number of affected rows* generally refers to the + number of rows deleted, updated or inserted by the last statement + run on the database cursor. Most databases will return the total + number of rows that were found by the corresponding ``WHERE`` + clause of the statement. Some databases use a different + interpretation for ``UPDATE``\s and only return the number of rows + that were changed by the ``UPDATE``, even though the ``WHERE`` + clause of the statement may have found more matching rows. + Database module authors should try to implement the more common + interpretation of returning the total number of rows found by the + ``WHERE`` clause, or clearly document a different interpretation + of the ``.rowcount`` attribute. + + +`Acknowledgements`_ +=================== + +Many thanks go to Andrew Kuchling who converted the Python Database +API Specification 2.0 from the original HTML format into the PEP +format. + +Many thanks to James Henstridge for leading the discussion which led +to the standardization of the two-phase commit API extensions. + +Many thanks to Daniele Varrazzo for converting the specification from +text PEP format to ReST PEP format, which allows linking to various +parts. + +`Copyright`_ +============ + +This document has been placed in the Public Domain. -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Nov 7 09:48:29 2012 From: python-checkins at python.org (hynek.schlawack) Date: Wed, 7 Nov 2012 09:48:29 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE1MDAx?= =?utf-8?b?OiBmaXggc2VnZmF1bHQgb24gImRlbCBzeXMubW9kdWxlc1snX19tYWluX18n?= =?utf-8?b?XSI=?= Message-ID: <3XxLrF12GDzPWM@mail.python.org> http://hg.python.org/cpython/rev/4ebe1ede981e changeset: 80292:4ebe1ede981e branch: 2.7 parent: 80258:1c54def5947c user: Hynek Schlawack date: Wed Nov 07 09:41:28 2012 +0100 summary: Issue #15001: fix segfault on "del sys.modules['__main__']" Patch by Victor Stinner. files: Lib/test/test_cmd_line.py | 19 +++++++++++++++++-- Misc/NEWS | 3 +++ Python/pythonrun.c | 10 +++++----- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -2,9 +2,12 @@ # All tests are executed with environment variables ignored # See test_cmd_line_script.py for testing of script execution -import test.test_support, unittest +import test.test_support import sys -from test.script_helper import spawn_python, kill_python, python_exit_code +import unittest +from test.script_helper import ( + assert_python_ok, spawn_python, kill_python, python_exit_code +) class CmdLineTest(unittest.TestCase): @@ -101,6 +104,18 @@ data = self.start_python('-R', '-c', code) self.assertTrue('hash_randomization=1' in data) + def test_del___main__(self): + # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a + # borrowed reference to the dict of __main__ module and later modify + # the dict whereas the module was destroyed + filename = test.test_support.TESTFN + self.addCleanup(test.test_support.unlink, filename) + with open(filename, "w") as script: + print >>script, "import sys" + print >>script, "del sys.modules['__main__']" + assert_python_ok(filename) + + def test_main(): test.test_support.run_unittest(CmdLineTest) test.test_support.reap_children() diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -9,6 +9,9 @@ Core and Builtins ----------------- +- Issue #15001: fix segfault on "del sys.modules['__main__']". Patch by Victor + Stinner. + - Issue #5057: the peepholer no longer optimizes subscription on unicode literals (e.g. u'foo'[0]) in order to produce compatible pyc files between narrow and wide builds. diff --git a/Python/pythonrun.c b/Python/pythonrun.c --- a/Python/pythonrun.c +++ b/Python/pythonrun.c @@ -907,19 +907,20 @@ { PyObject *m, *d, *v; const char *ext; - int set_file_name = 0, ret, len; + int set_file_name = 0, len, ret = -1; m = PyImport_AddModule("__main__"); if (m == NULL) return -1; + Py_INCREF(m); d = PyModule_GetDict(m); if (PyDict_GetItemString(d, "__file__") == NULL) { PyObject *f = PyString_FromString(filename); if (f == NULL) - return -1; + goto done; if (PyDict_SetItemString(d, "__file__", f) < 0) { Py_DECREF(f); - return -1; + goto done; } set_file_name = 1; Py_DECREF(f); @@ -932,7 +933,6 @@ fclose(fp); if ((fp = fopen(filename, "rb")) == NULL) { fprintf(stderr, "python: Can't reopen .pyc file\n"); - ret = -1; goto done; } /* Turn on optimization if a .pyo file is given */ @@ -945,7 +945,6 @@ } if (v == NULL) { PyErr_Print(); - ret = -1; goto done; } Py_DECREF(v); @@ -955,6 +954,7 @@ done: if (set_file_name && PyDict_DelItemString(d, "__file__")) PyErr_Clear(); + Py_DECREF(m); return ret; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 20:26:05 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 7 Nov 2012 20:26:05 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Path=2Ejoin=28=29_is_now_Path?= =?utf-8?b?LmpvaW5wYXRoKCk=?= Message-ID: <3Xxczx4NGzzPxQ@mail.python.org> http://hg.python.org/peps/rev/05bc7c4d40c0 changeset: 4579:05bc7c4d40c0 user: Antoine Pitrou date: Wed Nov 07 20:06:20 2012 +0100 summary: Path.join() is now Path.joinpath() files: pep-0428.txt | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pep-0428.txt b/pep-0428.txt --- a/pep-0428.txt +++ b/pep-0428.txt @@ -376,10 +376,10 @@ >>> p['bar', 'xyzzy'] PurePosixPath('foo/bar/xyzzy') -A join() method is also provided, with the same behaviour. It can serve +A joinpath() method is also provided, with the same behaviour. It can serve as a factory function:: - >>> path_factory = p.join + >>> path_factory = p.joinpath >>> path_factory('bar') PurePosixPath('foo/bar') -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Nov 7 20:26:06 2012 From: python-checkins at python.org (antoine.pitrou) Date: Wed, 7 Nov 2012 20:26:06 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?peps=3A_Replace_subscription_with_sla?= =?utf-8?q?shing?= Message-ID: <3Xxczy6lk8zQFK@mail.python.org> http://hg.python.org/peps/rev/0879efc1ea42 changeset: 4580:0879efc1ea42 user: Antoine Pitrou date: Wed Nov 07 20:25:27 2012 +0100 summary: Replace subscription with slashing files: pep-0428.txt | 12 +++++++----- 1 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pep-0428.txt b/pep-0428.txt --- a/pep-0428.txt +++ b/pep-0428.txt @@ -360,20 +360,22 @@ Joining ^^^^^^^ -A path can be joined with another using the ``__getitem__`` operator:: +A path can be joined with another using the ``/`` operator:: >>> p = PurePosixPath('foo') - >>> p['bar'] + >>> p / 'bar' PurePosixPath('foo/bar') - >>> p[PurePosixPath('bar')] + >>> p / PurePosixPath('bar') PurePosixPath('foo/bar') + >>> 'bar' / p + PurePosixPath('bar/foo') As with the constructor, multiple path components can be specified, either collapsed or separately:: - >>> p['bar/xyzzy'] + >>> p / 'bar/xyzzy' PurePosixPath('foo/bar/xyzzy') - >>> p['bar', 'xyzzy'] + >>> p / 'bar' / 'xyzzy' PurePosixPath('foo/bar/xyzzy') A joinpath() method is also provided, with the same behaviour. It can serve -- Repository URL: http://hg.python.org/peps From python-checkins at python.org Wed Nov 7 23:21:17 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 7 Nov 2012 23:21:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE2NDMx?= =?utf-8?q?=3A_Use_the_type_information_when_constructing_a_Decimal_subtyp?= =?utf-8?q?e?= Message-ID: <3Xxht55HS2zN6v@mail.python.org> http://hg.python.org/cpython/rev/1b6c972457e6 changeset: 80293:1b6c972457e6 branch: 3.3 parent: 80290:215297665098 user: Stefan Krah date: Wed Nov 07 23:12:25 2012 +0100 summary: Issue #16431: Use the type information when constructing a Decimal subtype from a Decimal argument. files: Lib/test/test_decimal.py | 5 ++++ Misc/NEWS | 3 ++ Modules/_decimal/_decimal.c | 29 +++++++++++++++++++++++- 3 files changed, 35 insertions(+), 2 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 @@ -2047,6 +2047,11 @@ self.assertIs(type(d), MyDecimal) self.assertEqual(d, d1) + a = Decimal('1.0') + b = MyDecimal(a) + self.assertIs(type(b), MyDecimal) + self.assertEqual(a, b) + def test_implicit_context(self): Decimal = self.decimal.Decimal getcontext = self.decimal.getcontext diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -80,6 +80,9 @@ Library ------- +- Issue #16431: Use the type information when constructing a Decimal subtype + from a Decimal argument. + - Issue #16350: zlib.Decompress.decompress() now accumulates data from successive calls after EOF in unused_data, instead of only saving the argument to the last call. Patch by Serhiy Storchaka. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2338,6 +2338,32 @@ return dec; } +/* Return a new PyDecObject (subtype) from a Decimal. */ +static PyObject * +PyDecType_FromDecimalExact(PyTypeObject *type, PyObject *v, PyObject *context) +{ + PyObject *dec; + uint32_t status = 0; + + if (type == &PyDec_Type) { + Py_INCREF(v); + return v; + } + + dec = PyDecType_New(type); + if (dec == NULL) { + return NULL; + } + + mpd_qcopy(MPD(dec), MPD(v), &status); + if (dec_addstatus(context, status)) { + Py_DECREF(dec); + return NULL; + } + + return dec; +} + static PyObject * sequence_as_tuple(PyObject *v, PyObject *ex, const char *mesg) { @@ -2642,8 +2668,7 @@ return PyDecType_FromSsizeExact(type, 0, context); } else if (PyDec_Check(v)) { - Py_INCREF(v); - return v; + return PyDecType_FromDecimalExact(type, v, context); } else if (PyUnicode_Check(v)) { return PyDecType_FromUnicodeExactWS(type, v, context); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 23:21:19 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 7 Nov 2012 23:21:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4zLg==?= Message-ID: <3Xxht70yyyzPbX@mail.python.org> http://hg.python.org/cpython/rev/57649a9a683c changeset: 80294:57649a9a683c parent: 80291:859ef54bdce2 parent: 80293:1b6c972457e6 user: Stefan Krah date: Wed Nov 07 23:20:10 2012 +0100 summary: Merge 3.3. files: Lib/test/test_decimal.py | 5 ++++ Misc/NEWS | 3 ++ Modules/_decimal/_decimal.c | 29 +++++++++++++++++++++++- 3 files changed, 35 insertions(+), 2 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 @@ -2047,6 +2047,11 @@ self.assertIs(type(d), MyDecimal) self.assertEqual(d, d1) + a = Decimal('1.0') + b = MyDecimal(a) + self.assertIs(type(b), MyDecimal) + self.assertEqual(a, b) + def test_implicit_context(self): Decimal = self.decimal.Decimal getcontext = self.decimal.getcontext diff --git a/Misc/NEWS b/Misc/NEWS --- a/Misc/NEWS +++ b/Misc/NEWS @@ -110,6 +110,9 @@ Library ------- +- Issue #16431: Use the type information when constructing a Decimal subtype + from a Decimal argument. + - Issue #15641: Clean up deprecated classes from importlib Patch by Taras Lyapun. diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2338,6 +2338,32 @@ return dec; } +/* Return a new PyDecObject (subtype) from a Decimal. */ +static PyObject * +PyDecType_FromDecimalExact(PyTypeObject *type, PyObject *v, PyObject *context) +{ + PyObject *dec; + uint32_t status = 0; + + if (type == &PyDec_Type) { + Py_INCREF(v); + return v; + } + + dec = PyDecType_New(type); + if (dec == NULL) { + return NULL; + } + + mpd_qcopy(MPD(dec), MPD(v), &status); + if (dec_addstatus(context, status)) { + Py_DECREF(dec); + return NULL; + } + + return dec; +} + static PyObject * sequence_as_tuple(PyObject *v, PyObject *ex, const char *mesg) { @@ -2642,8 +2668,7 @@ return PyDecType_FromSsizeExact(type, 0, context); } else if (PyDec_Check(v)) { - Py_INCREF(v); - return v; + return PyDecType_FromDecimalExact(type, v, context); } else if (PyUnicode_Check(v)) { return PyDecType_FromUnicodeExactWS(type, v, context); -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 23:55:16 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 7 Nov 2012 23:55:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE2NDMx?= =?utf-8?q?=3A_Also_fix_the_opposite_direction=2E?= Message-ID: <3XxjdJ6bBlzN6v@mail.python.org> http://hg.python.org/cpython/rev/7fcc58811e82 changeset: 80295:7fcc58811e82 branch: 3.3 parent: 80293:1b6c972457e6 user: Stefan Krah date: Wed Nov 07 23:47:19 2012 +0100 summary: Issue #16431: Also fix the opposite direction. files: Lib/test/test_decimal.py | 4 ++++ Modules/_decimal/_decimal.c | 2 +- 2 files changed, 5 insertions(+), 1 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 @@ -2052,6 +2052,10 @@ self.assertIs(type(b), MyDecimal) self.assertEqual(a, b) + c = Decimal(b) + self.assertIs(type(c), Decimal) + self.assertEqual(a, c) + def test_implicit_context(self): Decimal = self.decimal.Decimal getcontext = self.decimal.getcontext diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2345,7 +2345,7 @@ PyObject *dec; uint32_t status = 0; - if (type == &PyDec_Type) { + if (type == Py_TYPE(v)) { Py_INCREF(v); return v; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Wed Nov 7 23:55:18 2012 From: python-checkins at python.org (stefan.krah) Date: Wed, 7 Nov 2012 23:55:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4zLg==?= Message-ID: <3XxjdL1vZrzPCN@mail.python.org> http://hg.python.org/cpython/rev/5fd9b87e08b3 changeset: 80296:5fd9b87e08b3 parent: 80294:57649a9a683c parent: 80295:7fcc58811e82 user: Stefan Krah date: Wed Nov 07 23:54:37 2012 +0100 summary: Merge 3.3. files: Lib/test/test_decimal.py | 4 ++++ Modules/_decimal/_decimal.c | 2 +- 2 files changed, 5 insertions(+), 1 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 @@ -2052,6 +2052,10 @@ self.assertIs(type(b), MyDecimal) self.assertEqual(a, b) + c = Decimal(b) + self.assertIs(type(c), Decimal) + self.assertEqual(a, c) + def test_implicit_context(self): Decimal = self.decimal.Decimal getcontext = self.decimal.getcontext diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2345,7 +2345,7 @@ PyObject *dec; uint32_t status = 0; - if (type == &PyDec_Type) { + if (type == Py_TYPE(v)) { Py_INCREF(v); return v; } -- Repository URL: http://hg.python.org/cpython From solipsis at pitrou.net Thu Nov 8 05:55:51 2012 From: solipsis at pitrou.net (solipsis at pitrou.net) Date: Thu, 08 Nov 2012 05:55:51 +0100 Subject: [Python-checkins] Daily reference leaks (5fd9b87e08b3): sum=0 Message-ID: results for 5fd9b87e08b3 on branch "default" -------------------------------------------- Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/antoine/cpython/refleaks/reflog4eEjRu', '-x'] From python-checkins at python.org Thu Nov 8 09:12:16 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 09:12:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzEwMzg1OiB1c2Ug?= =?utf-8?q?the_mod_role_in_subprocess_docs=2E?= Message-ID: <3Xxy003Y7szMQl@mail.python.org> http://hg.python.org/cpython/rev/58564aeec8e4 changeset: 80297:58564aeec8e4 branch: 2.7 parent: 80292:4ebe1ede981e user: Ezio Melotti date: Thu Nov 08 10:07:10 2012 +0200 summary: #10385: use the mod role in subprocess docs. files: Doc/library/subprocess.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -28,8 +28,8 @@ :pep:`324` -- PEP proposing the subprocess module -Using the subprocess Module ---------------------------- +Using the :mod:`subprocess` Module +---------------------------------- The recommended approach to invoking subprocesses is to use the following convenience functions for all use cases they can handle. For more advanced @@ -680,8 +680,8 @@ .. _subprocess-replacements: -Replacing Older Functions with the subprocess Module ----------------------------------------------------- +Replacing Older Functions with the :mod:`subprocess` Module +----------------------------------------------------------- In this section, "a becomes b" means that b can be used as a replacement for a. @@ -697,7 +697,7 @@ the raised exception. In the following examples, we assume that the relevant functions have already -been imported from the subprocess module. +been imported from the :mod:`subprocess` module. Replacing /bin/sh shell backquote -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 09:12:17 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 09:12:17 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzEwMzg1OiB1c2Ug?= =?utf-8?q?the_mod_role_in_subprocess_docs=2E?= Message-ID: <3Xxy0160CLzMR5@mail.python.org> http://hg.python.org/cpython/rev/8e8d391eb3eb changeset: 80298:8e8d391eb3eb branch: 3.2 parent: 80249:56bc323288d1 user: Ezio Melotti date: Thu Nov 08 10:07:10 2012 +0200 summary: #10385: use the mod role in subprocess docs. files: Doc/library/subprocess.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -22,8 +22,8 @@ :pep:`324` -- PEP proposing the subprocess module -Using the subprocess Module ---------------------------- +Using the :mod:`subprocess` Module +---------------------------------- The recommended approach to invoking subprocesses is to use the following convenience functions for all use cases they can handle. For more advanced @@ -731,8 +731,8 @@ .. _subprocess-replacements: -Replacing Older Functions with the subprocess Module ----------------------------------------------------- +Replacing Older Functions with the :mod:`subprocess` Module +----------------------------------------------------------- In this section, "a becomes b" means that b can be used as a replacement for a. @@ -748,7 +748,7 @@ the raised exception. In the following examples, we assume that the relevant functions have already -been imported from the subprocess module. +been imported from the :mod:`subprocess` module. Replacing /bin/sh shell backquote -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 09:12:19 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 09:12:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2310385=3A_merge_with_3=2E2=2E?= Message-ID: <3Xxy0317VJzMkr@mail.python.org> http://hg.python.org/cpython/rev/f45d1afb952b changeset: 80299:f45d1afb952b branch: 3.3 parent: 80295:7fcc58811e82 parent: 80298:8e8d391eb3eb user: Ezio Melotti date: Thu Nov 08 10:09:06 2012 +0200 summary: #10385: merge with 3.2. files: Doc/library/subprocess.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -22,8 +22,8 @@ :pep:`324` -- PEP proposing the subprocess module -Using the subprocess Module ---------------------------- +Using the :mod:`subprocess` Module +---------------------------------- The recommended approach to invoking subprocesses is to use the following convenience functions for all use cases they can handle. For more advanced @@ -839,8 +839,8 @@ .. _subprocess-replacements: -Replacing Older Functions with the subprocess Module ----------------------------------------------------- +Replacing Older Functions with the :mod:`subprocess` Module +----------------------------------------------------------- In this section, "a becomes b" means that b can be used as a replacement for a. @@ -856,7 +856,7 @@ the raised exception. In the following examples, we assume that the relevant functions have already -been imported from the subprocess module. +been imported from the :mod:`subprocess` module. Replacing /bin/sh shell backquote -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 09:12:20 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 09:12:20 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzEwMzg1OiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3Xxy043SG1zN6k@mail.python.org> http://hg.python.org/cpython/rev/5d7e7e7e2e82 changeset: 80300:5d7e7e7e2e82 parent: 80296:5fd9b87e08b3 parent: 80299:f45d1afb952b user: Ezio Melotti date: Thu Nov 08 10:09:24 2012 +0200 summary: #10385: merge with 3.3. files: Doc/library/subprocess.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -22,8 +22,8 @@ :pep:`324` -- PEP proposing the subprocess module -Using the subprocess Module ---------------------------- +Using the :mod:`subprocess` Module +---------------------------------- The recommended approach to invoking subprocesses is to use the following convenience functions for all use cases they can handle. For more advanced @@ -839,8 +839,8 @@ .. _subprocess-replacements: -Replacing Older Functions with the subprocess Module ----------------------------------------------------- +Replacing Older Functions with the :mod:`subprocess` Module +----------------------------------------------------------- In this section, "a becomes b" means that b can be used as a replacement for a. @@ -856,7 +856,7 @@ the raised exception. In the following examples, we assume that the relevant functions have already -been imported from the subprocess module. +been imported from the :mod:`subprocess` module. Replacing /bin/sh shell backquote -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 09:12:21 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 09:12:21 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMik6?= =?utf-8?q?_Merge_heads=2E?= Message-ID: <3Xxy055ZzgzNQ6@mail.python.org> http://hg.python.org/cpython/rev/ea04a7d2407d changeset: 80301:ea04a7d2407d branch: 3.2 parent: 80289:b256d054f229 parent: 80298:8e8d391eb3eb user: Ezio Melotti date: Thu Nov 08 10:11:22 2012 +0200 summary: Merge heads. files: Doc/library/subprocess.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/subprocess.rst b/Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst +++ b/Doc/library/subprocess.rst @@ -22,8 +22,8 @@ :pep:`324` -- PEP proposing the subprocess module -Using the subprocess Module ---------------------------- +Using the :mod:`subprocess` Module +---------------------------------- The recommended approach to invoking subprocesses is to use the following convenience functions for all use cases they can handle. For more advanced @@ -731,8 +731,8 @@ .. _subprocess-replacements: -Replacing Older Functions with the subprocess Module ----------------------------------------------------- +Replacing Older Functions with the :mod:`subprocess` Module +----------------------------------------------------------- In this section, "a becomes b" means that b can be used as a replacement for a. @@ -748,7 +748,7 @@ the raised exception. In the following examples, we assume that the relevant functions have already -been imported from the subprocess module. +been imported from the :mod:`subprocess` module. Replacing /bin/sh shell backquote -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:06:31 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:06:31 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzExNDgxOiB1cGRh?= =?utf-8?q?te_copy=5Freg_docs_and_add_example=2E?= Message-ID: <3XxzBb2stTzMG3@mail.python.org> http://hg.python.org/cpython/rev/2bd6150b48ea changeset: 80302:2bd6150b48ea branch: 2.7 parent: 80297:58564aeec8e4 user: Ezio Melotti date: Thu Nov 08 10:59:03 2012 +0200 summary: #11481: update copy_reg docs and add example. files: Doc/library/copy_reg.rst | 31 +++++++++++++++++++++++---- 1 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Doc/library/copy_reg.rst b/Doc/library/copy_reg.rst --- a/Doc/library/copy_reg.rst +++ b/Doc/library/copy_reg.rst @@ -14,11 +14,11 @@ module: cPickle module: copy -The :mod:`copy_reg` module provides support for the :mod:`pickle` and -:mod:`cPickle` modules. The :mod:`copy` module is likely to use this in the -future as well. It provides configuration information about object constructors -which are not classes. Such constructors may be factory functions or class -instances. +The :mod:`copy_reg` module offers a way to define fuctions used while pickling +specific objects. The :mod:`pickle`, :mod:`cPickle, and :mod:`copy` modules +use those functions when pickling/copying those objects. The module provides +configuration information about object constructors which are not classes. +Such constructors may be factory functions or class instances. .. function:: constructor(object) @@ -43,3 +43,24 @@ See the :mod:`pickle` module for more details on the interface expected of *function* and *constructor*. +Example +------- + +The example below would like to show how to register a pickle function and how +it will be used: + + >>> import copy_reg, copy, pickle + >>> class C(object): + ... def __init__(self, a): + ... self.a = a + ... + >>> def pickle_c(c): + ... print("pickling a C instance...") + ... return C, (c.a,) + ... + >>> copy_reg.pickle(C, pickle_c) + >>> c = C(1) + >>> d = copy.copy(c) + pickling a C instance... + >>> p = pickle.dumps(c) + pickling a C instance... -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:06:32 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:06:32 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzExNDgxOiBmaXgg?= =?utf-8?q?markup=2E?= Message-ID: <3XxzBc5Q0VzN6c@mail.python.org> http://hg.python.org/cpython/rev/e089bdca9d9c changeset: 80303:e089bdca9d9c branch: 2.7 user: Ezio Melotti date: Thu Nov 08 11:02:58 2012 +0200 summary: #11481: fix markup. files: Doc/library/copy_reg.rst | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Doc/library/copy_reg.rst b/Doc/library/copy_reg.rst --- a/Doc/library/copy_reg.rst +++ b/Doc/library/copy_reg.rst @@ -15,7 +15,7 @@ module: copy The :mod:`copy_reg` module offers a way to define fuctions used while pickling -specific objects. The :mod:`pickle`, :mod:`cPickle, and :mod:`copy` modules +specific objects. The :mod:`pickle`, :mod:`cPickle`, and :mod:`copy` modules use those functions when pickling/copying those objects. The module provides configuration information about object constructors which are not classes. Such constructors may be factory functions or class instances. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:06:34 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:06:34 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzExNDgxOiB1cGRh?= =?utf-8?q?te_copyreg_docs_and_add_example=2E?= Message-ID: <3XxzBf0bFrzMrs@mail.python.org> http://hg.python.org/cpython/rev/12dbb3187105 changeset: 80304:12dbb3187105 branch: 3.2 parent: 80301:ea04a7d2407d user: Ezio Melotti date: Thu Nov 08 11:04:57 2012 +0200 summary: #11481: update copyreg docs and add example. files: Doc/library/copy.rst | 4 ++-- Doc/library/copyreg.rst | 29 ++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -67,8 +67,8 @@ Classes can use the same interfaces to control copying that they use to control pickling. See the description of module :mod:`pickle` for information on these -methods. The :mod:`copy` module does not use the :mod:`copyreg` registration -module. +methods. In fact, :mod:`copy` module uses the registered pickle functions from +:mod:`copyreg` module. .. index:: single: __copy__() (copy protocol) diff --git a/Doc/library/copyreg.rst b/Doc/library/copyreg.rst --- a/Doc/library/copyreg.rst +++ b/Doc/library/copyreg.rst @@ -9,9 +9,10 @@ module: pickle module: copy -The :mod:`copyreg` module provides support for the :mod:`pickle` module. The -:mod:`copy` module is likely to use this in the future as well. It provides -configuration information about object constructors which are not classes. +The :mod:`copyreg` module offers a way to define fuctions used while pickling +specific objects. The :mod:`pickle` and :mod:`copy` modules use those functions +when pickling/copying those objects. The module provides configuration +information about object constructors which are not classes. Such constructors may be factory functions or class instances. @@ -35,3 +36,25 @@ See the :mod:`pickle` module for more details on the interface expected of *function* and *constructor*. + +Example +------- + +The example below would like to show how to register a pickle function and how +it will be used: + + >>> import copyreg, copy, pickle + >>> class C(object): + ... def __init__(self, a): + ... self.a = a + ... + >>> def pickle_c(c): + ... print("pickling a C instance...") + ... return C, (c.a,) + ... + >>> copyreg.pickle(C, pickle_c) + >>> c = C(1) + >>> d = copy.copy(c) + pickling a C instance... + >>> p = pickle.dumps(c) + pickling a C instance... -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:06:35 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:06:35 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2311481=3A_merge_with_3=2E2=2E?= Message-ID: <3XxzBg2v1QzNQ6@mail.python.org> http://hg.python.org/cpython/rev/87ec3ce3a04e changeset: 80305:87ec3ce3a04e branch: 3.3 parent: 80299:f45d1afb952b parent: 80304:12dbb3187105 user: Ezio Melotti date: Thu Nov 08 11:06:01 2012 +0200 summary: #11481: merge with 3.2. files: Doc/library/copy.rst | 4 ++-- Doc/library/copyreg.rst | 29 ++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -67,8 +67,8 @@ Classes can use the same interfaces to control copying that they use to control pickling. See the description of module :mod:`pickle` for information on these -methods. The :mod:`copy` module does not use the :mod:`copyreg` registration -module. +methods. In fact, :mod:`copy` module uses the registered pickle functions from +:mod:`copyreg` module. .. index:: single: __copy__() (copy protocol) diff --git a/Doc/library/copyreg.rst b/Doc/library/copyreg.rst --- a/Doc/library/copyreg.rst +++ b/Doc/library/copyreg.rst @@ -9,9 +9,10 @@ module: pickle module: copy -The :mod:`copyreg` module provides support for the :mod:`pickle` module. The -:mod:`copy` module is likely to use this in the future as well. It provides -configuration information about object constructors which are not classes. +The :mod:`copyreg` module offers a way to define fuctions used while pickling +specific objects. The :mod:`pickle` and :mod:`copy` modules use those functions +when pickling/copying those objects. The module provides configuration +information about object constructors which are not classes. Such constructors may be factory functions or class instances. @@ -37,3 +38,25 @@ :attr:`~pickle.Pickler.dispatch_table` attribute of a pickler object or subclass of :class:`pickle.Pickler` can also be used for declaring reduction functions. + +Example +------- + +The example below would like to show how to register a pickle function and how +it will be used: + + >>> import copyreg, copy, pickle + >>> class C(object): + ... def __init__(self, a): + ... self.a = a + ... + >>> def pickle_c(c): + ... print("pickling a C instance...") + ... return C, (c.a,) + ... + >>> copyreg.pickle(C, pickle_c) + >>> c = C(1) + >>> d = copy.copy(c) + pickling a C instance... + >>> p = pickle.dumps(c) + pickling a C instance... -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:06:36 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:06:36 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzExNDgxOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3XxzBh59l9zMGP@mail.python.org> http://hg.python.org/cpython/rev/20b65b88e0a0 changeset: 80306:20b65b88e0a0 parent: 80300:5d7e7e7e2e82 parent: 80305:87ec3ce3a04e user: Ezio Melotti date: Thu Nov 08 11:06:19 2012 +0200 summary: #11481: merge with 3.3. files: Doc/library/copy.rst | 4 ++-- Doc/library/copyreg.rst | 29 ++++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Doc/library/copy.rst b/Doc/library/copy.rst --- a/Doc/library/copy.rst +++ b/Doc/library/copy.rst @@ -67,8 +67,8 @@ Classes can use the same interfaces to control copying that they use to control pickling. See the description of module :mod:`pickle` for information on these -methods. The :mod:`copy` module does not use the :mod:`copyreg` registration -module. +methods. In fact, :mod:`copy` module uses the registered pickle functions from +:mod:`copyreg` module. .. index:: single: __copy__() (copy protocol) diff --git a/Doc/library/copyreg.rst b/Doc/library/copyreg.rst --- a/Doc/library/copyreg.rst +++ b/Doc/library/copyreg.rst @@ -9,9 +9,10 @@ module: pickle module: copy -The :mod:`copyreg` module provides support for the :mod:`pickle` module. The -:mod:`copy` module is likely to use this in the future as well. It provides -configuration information about object constructors which are not classes. +The :mod:`copyreg` module offers a way to define fuctions used while pickling +specific objects. The :mod:`pickle` and :mod:`copy` modules use those functions +when pickling/copying those objects. The module provides configuration +information about object constructors which are not classes. Such constructors may be factory functions or class instances. @@ -37,3 +38,25 @@ :attr:`~pickle.Pickler.dispatch_table` attribute of a pickler object or subclass of :class:`pickle.Pickler` can also be used for declaring reduction functions. + +Example +------- + +The example below would like to show how to register a pickle function and how +it will be used: + + >>> import copyreg, copy, pickle + >>> class C(object): + ... def __init__(self, a): + ... self.a = a + ... + >>> def pickle_c(c): + ... print("pickling a C instance...") + ... return C, (c.a,) + ... + >>> copyreg.pickle(C, pickle_c) + >>> c = C(1) + >>> d = copy.copy(c) + pickling a C instance... + >>> p = pickle.dumps(c) + pickling a C instance... -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:09:42 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:09:42 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE2NDMzOiBmaXgg?= =?utf-8?q?docstring_of_assertNotEqual=2E?= Message-ID: <3XxzGG2qSKzM1V@mail.python.org> http://hg.python.org/cpython/rev/d32d04edd371 changeset: 80307:d32d04edd371 branch: 2.7 parent: 80303:e089bdca9d9c user: Ezio Melotti date: Thu Nov 08 11:08:39 2012 +0200 summary: #16433: fix docstring of assertNotEqual. files: Lib/unittest/case.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -516,7 +516,7 @@ assertion_func(first, second, msg=msg) def assertNotEqual(self, first, second, msg=None): - """Fail if the two objects are equal as determined by the '==' + """Fail if the two objects are equal as determined by the '!=' operator. """ if not first != second: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:09:43 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:09:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE2NDMzOiBmaXgg?= =?utf-8?q?docstring_of_assertNotEqual=2E?= Message-ID: <3XxzGH5Qh3zMPk@mail.python.org> http://hg.python.org/cpython/rev/9d5cc978cfe5 changeset: 80308:9d5cc978cfe5 branch: 3.2 parent: 80304:12dbb3187105 user: Ezio Melotti date: Thu Nov 08 11:08:39 2012 +0200 summary: #16433: fix docstring of assertNotEqual. files: Lib/unittest/case.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -628,7 +628,7 @@ assertion_func(first, second, msg=msg) def assertNotEqual(self, first, second, msg=None): - """Fail if the two objects are equal as determined by the '==' + """Fail if the two objects are equal as determined by the '!=' operator. """ if not first != second: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:09:45 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:09:45 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2316433=3A_merge_with_3=2E2=2E?= Message-ID: <3XxzGK0zkhzN6c@mail.python.org> http://hg.python.org/cpython/rev/e0fe5eead38a changeset: 80309:e0fe5eead38a branch: 3.3 parent: 80305:87ec3ce3a04e parent: 80308:9d5cc978cfe5 user: Ezio Melotti date: Thu Nov 08 11:09:13 2012 +0200 summary: #16433: merge with 3.2. files: Lib/unittest/case.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -642,7 +642,7 @@ assertion_func(first, second, msg=msg) def assertNotEqual(self, first, second, msg=None): - """Fail if the two objects are equal as determined by the '==' + """Fail if the two objects are equal as determined by the '!=' operator. """ if not first != second: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 10:09:46 2012 From: python-checkins at python.org (ezio.melotti) Date: Thu, 8 Nov 2012 10:09:46 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE2NDMzOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3XxzGL4FlDzPbX@mail.python.org> http://hg.python.org/cpython/rev/6eba4df6bb21 changeset: 80310:6eba4df6bb21 parent: 80306:20b65b88e0a0 parent: 80309:e0fe5eead38a user: Ezio Melotti date: Thu Nov 08 11:09:28 2012 +0200 summary: #16433: merge with 3.3. files: Lib/unittest/case.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/Lib/unittest/case.py b/Lib/unittest/case.py --- a/Lib/unittest/case.py +++ b/Lib/unittest/case.py @@ -642,7 +642,7 @@ assertion_func(first, second, msg=msg) def assertNotEqual(self, first, second, msg=None): - """Fail if the two objects are equal as determined by the '==' + """Fail if the two objects are equal as determined by the '!=' operator. """ if not first != second: -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 11:20:41 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 8 Nov 2012 11:20:41 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4zKTogSXNzdWUgIzE2NDMx?= =?utf-8?q?=3A_Finally=2C_consider_all_permutations=2E?= Message-ID: <3Xy0r95xpCzMWT@mail.python.org> http://hg.python.org/cpython/rev/9a701e8ec2c9 changeset: 80311:9a701e8ec2c9 branch: 3.3 parent: 80309:e0fe5eead38a user: Stefan Krah date: Thu Nov 08 11:17:29 2012 +0100 summary: Issue #16431: Finally, consider all permutations. files: Lib/test/test_decimal.py | 33 ++++++++++++++++++------ Modules/_decimal/_decimal.c | 4 +- 2 files changed, 26 insertions(+), 11 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 @@ -2029,7 +2029,7 @@ Decimal = self.decimal.Decimal class MyDecimal(Decimal): - pass + y = None d1 = MyDecimal(1) d2 = MyDecimal(2) @@ -2047,14 +2047,29 @@ self.assertIs(type(d), MyDecimal) self.assertEqual(d, d1) - a = Decimal('1.0') - b = MyDecimal(a) - self.assertIs(type(b), MyDecimal) - self.assertEqual(a, b) - - c = Decimal(b) - self.assertIs(type(c), Decimal) - self.assertEqual(a, c) + # Decimal(Decimal) + d = Decimal('1.0') + x = Decimal(d) + self.assertIs(type(x), Decimal) + self.assertEqual(x, d) + + # MyDecimal(Decimal) + m = MyDecimal(d) + self.assertIs(type(m), MyDecimal) + self.assertEqual(m, d) + self.assertIs(m.y, None) + + # Decimal(MyDecimal) + x = Decimal(m) + self.assertIs(type(x), Decimal) + self.assertEqual(x, d) + + # MyDecimal(MyDecimal) + m.y = 9 + x = MyDecimal(m) + self.assertIs(type(x), MyDecimal) + self.assertEqual(x, d) + self.assertIs(x.y, None) def test_implicit_context(self): Decimal = self.decimal.Decimal diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2338,14 +2338,14 @@ return dec; } -/* Return a new PyDecObject (subtype) from a Decimal. */ +/* Return a new PyDecObject or a subtype from a Decimal. */ static PyObject * PyDecType_FromDecimalExact(PyTypeObject *type, PyObject *v, PyObject *context) { PyObject *dec; uint32_t status = 0; - if (type == Py_TYPE(v)) { + if (type == &PyDec_Type && PyDec_CheckExact(v)) { Py_INCREF(v); return v; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 11:20:43 2012 From: python-checkins at python.org (stefan.krah) Date: Thu, 8 Nov 2012 11:20:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogTWVyZ2UgMy4zLg==?= Message-ID: <3Xy0rC1Z04zN6c@mail.python.org> http://hg.python.org/cpython/rev/b59f021a71c7 changeset: 80312:b59f021a71c7 parent: 80310:6eba4df6bb21 parent: 80311:9a701e8ec2c9 user: Stefan Krah date: Thu Nov 08 11:19:55 2012 +0100 summary: Merge 3.3. files: Lib/test/test_decimal.py | 33 ++++++++++++++++++------ Modules/_decimal/_decimal.c | 4 +- 2 files changed, 26 insertions(+), 11 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 @@ -2029,7 +2029,7 @@ Decimal = self.decimal.Decimal class MyDecimal(Decimal): - pass + y = None d1 = MyDecimal(1) d2 = MyDecimal(2) @@ -2047,14 +2047,29 @@ self.assertIs(type(d), MyDecimal) self.assertEqual(d, d1) - a = Decimal('1.0') - b = MyDecimal(a) - self.assertIs(type(b), MyDecimal) - self.assertEqual(a, b) - - c = Decimal(b) - self.assertIs(type(c), Decimal) - self.assertEqual(a, c) + # Decimal(Decimal) + d = Decimal('1.0') + x = Decimal(d) + self.assertIs(type(x), Decimal) + self.assertEqual(x, d) + + # MyDecimal(Decimal) + m = MyDecimal(d) + self.assertIs(type(m), MyDecimal) + self.assertEqual(m, d) + self.assertIs(m.y, None) + + # Decimal(MyDecimal) + x = Decimal(m) + self.assertIs(type(x), Decimal) + self.assertEqual(x, d) + + # MyDecimal(MyDecimal) + m.y = 9 + x = MyDecimal(m) + self.assertIs(type(x), MyDecimal) + self.assertEqual(x, d) + self.assertIs(x.y, None) def test_implicit_context(self): Decimal = self.decimal.Decimal diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -2338,14 +2338,14 @@ return dec; } -/* Return a new PyDecObject (subtype) from a Decimal. */ +/* Return a new PyDecObject or a subtype from a Decimal. */ static PyObject * PyDecType_FromDecimalExact(PyTypeObject *type, PyObject *v, PyObject *context) { PyObject *dec; uint32_t status = 0; - if (type == Py_TYPE(v)) { + if (type == &PyDec_Type && PyDec_CheckExact(v)) { Py_INCREF(v); return v; } -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 15:11:57 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 8 Nov 2012 15:11:57 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE2NDM1?= =?utf-8?q?=3A_Link_in_tutorial_now_points_to_python3_FAQ=2E?= Message-ID: <3Xy5z15R6wzMPk@mail.python.org> http://hg.python.org/cpython/rev/64527cb2e13a changeset: 80313:64527cb2e13a branch: 3.2 parent: 80308:9d5cc978cfe5 user: Andrew Svetlov date: Thu Nov 08 16:10:49 2012 +0200 summary: Issue #16435: Link in tutorial now points to python3 FAQ. Thanks to Yongzhi Pan from docs@ files: Doc/tutorial/whatnow.rst | 12 +++++------- 1 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -60,14 +60,12 @@ around 120 postings a day (with peaks up to several hundred), asking (and answering) questions, suggesting new features, and announcing new modules. Before posting, be sure to check the list of `Frequently Asked Questions -`_ (also called the FAQ), or look for it in the -:file:`Misc/` directory of the Python source distribution. Mailing list -archives are available at http://mail.python.org/pipermail/. The FAQ answers -many of the questions that come up again and again, and may already contain the -solution for your problem. +`_ (also called the FAQ), +or look for it in the :file:`Misc/` directory of the Python source distribution. +Mailing list archives are available at http://mail.python.org/pipermail/. +The FAQ answers many of the questions that come up again and again, +and may already contain the solution for your problem. .. Postings figure based on average of last six months activity as reported by www.egroups.com; Jan. 2000 - June 2000: 21272 msgs / 182 days = 116.9 msgs / day and steadily increasing. (XXX up to date figures?) - - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 15:11:59 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 8 Nov 2012 15:11:59 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_issue_=2316435=3A_Link_in_tutorial_now_points_to_python3?= =?utf-8?q?_FAQ=2E?= Message-ID: <3Xy5z30lGxzMWT@mail.python.org> http://hg.python.org/cpython/rev/1d5ca20f73e2 changeset: 80314:1d5ca20f73e2 branch: 3.3 parent: 80311:9a701e8ec2c9 parent: 80313:64527cb2e13a user: Andrew Svetlov date: Thu Nov 08 16:11:22 2012 +0200 summary: Merge issue #16435: Link in tutorial now points to python3 FAQ. Thanks to Yongzhi Pan from docs@ files: Doc/tutorial/whatnow.rst | 12 +++++------- 1 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -60,14 +60,12 @@ around 120 postings a day (with peaks up to several hundred), asking (and answering) questions, suggesting new features, and announcing new modules. Before posting, be sure to check the list of `Frequently Asked Questions -`_ (also called the FAQ), or look for it in the -:file:`Misc/` directory of the Python source distribution. Mailing list -archives are available at http://mail.python.org/pipermail/. The FAQ answers -many of the questions that come up again and again, and may already contain the -solution for your problem. +`_ (also called the FAQ), +or look for it in the :file:`Misc/` directory of the Python source distribution. +Mailing list archives are available at http://mail.python.org/pipermail/. +The FAQ answers many of the questions that come up again and again, +and may already contain the solution for your problem. .. Postings figure based on average of last six months activity as reported by www.egroups.com; Jan. 2000 - June 2000: 21272 msgs / 182 days = 116.9 msgs / day and steadily increasing. (XXX up to date figures?) - - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 15:12:00 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 8 Nov 2012 15:12:00 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_issue_=2316435=3A_Link_in_tutorial_now_points_to_p?= =?utf-8?q?ython3_FAQ=2E?= Message-ID: <3Xy5z431RFzP3k@mail.python.org> http://hg.python.org/cpython/rev/e1e019b3d903 changeset: 80315:e1e019b3d903 parent: 80312:b59f021a71c7 parent: 80314:1d5ca20f73e2 user: Andrew Svetlov date: Thu Nov 08 16:11:44 2012 +0200 summary: Merge issue #16435: Link in tutorial now points to python3 FAQ. Thanks to Yongzhi Pan from docs@ files: Doc/tutorial/whatnow.rst | 12 +++++------- 1 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Doc/tutorial/whatnow.rst b/Doc/tutorial/whatnow.rst --- a/Doc/tutorial/whatnow.rst +++ b/Doc/tutorial/whatnow.rst @@ -60,14 +60,12 @@ around 120 postings a day (with peaks up to several hundred), asking (and answering) questions, suggesting new features, and announcing new modules. Before posting, be sure to check the list of `Frequently Asked Questions -`_ (also called the FAQ), or look for it in the -:file:`Misc/` directory of the Python source distribution. Mailing list -archives are available at http://mail.python.org/pipermail/. The FAQ answers -many of the questions that come up again and again, and may already contain the -solution for your problem. +`_ (also called the FAQ), +or look for it in the :file:`Misc/` directory of the Python source distribution. +Mailing list archives are available at http://mail.python.org/pipermail/. +The FAQ answers many of the questions that come up again and again, +and may already contain the solution for your problem. .. Postings figure based on average of last six months activity as reported by www.egroups.com; Jan. 2000 - June 2000: 21272 msgs / 182 days = 116.9 msgs / day and steadily increasing. (XXX up to date figures?) - - -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 16:29:15 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 8 Nov 2012 16:29:15 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogSXNzdWUgIzE2NDM5?= =?utf-8?q?=3A_Fix_markup_in_example_for_stdtypes=2E?= Message-ID: <3Xy7hC1SsxzPW1@mail.python.org> http://hg.python.org/cpython/rev/aeb5c53a1d69 changeset: 80316:aeb5c53a1d69 branch: 3.2 parent: 80313:64527cb2e13a user: Andrew Svetlov date: Thu Nov 08 17:26:53 2012 +0200 summary: Issue #16439: Fix markup in example for stdtypes. Thanks to Yongzhi Pan. files: Doc/library/stdtypes.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1390,11 +1390,11 @@ >>> import re >>> def titlecase(s): - return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", - lambda mo: mo.group(0)[0].upper() + - mo.group(0)[1:].lower(), - s) - + ... return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", + ... lambda mo: mo.group(0)[0].upper() + + ... mo.group(0)[1:].lower(), + ... s) + ... >>> titlecase("they're bill's friends.") "They're Bill's Friends." -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 16:29:16 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 8 Nov 2012 16:29:16 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_Merge_issue_=2316439=3A_Fix_markup_in_example_for_stdtypes=2E?= Message-ID: <3Xy7hD4VLjzPpJ@mail.python.org> http://hg.python.org/cpython/rev/65499860c6f8 changeset: 80317:65499860c6f8 branch: 3.3 parent: 80314:1d5ca20f73e2 parent: 80316:aeb5c53a1d69 user: Andrew Svetlov date: Thu Nov 08 17:27:39 2012 +0200 summary: Merge issue #16439: Fix markup in example for stdtypes. Thanks to Yongzhi Pan. files: Doc/library/stdtypes.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1832,11 +1832,11 @@ >>> import re >>> def titlecase(s): - return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", - lambda mo: mo.group(0)[0].upper() + - mo.group(0)[1:].lower(), - s) - + ... return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", + ... lambda mo: mo.group(0)[0].upper() + + ... mo.group(0)[1:].lower(), + ... s) + ... >>> titlecase("they're bill's friends.") "They're Bill's Friends." -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 16:29:18 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 8 Nov 2012 16:29:18 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?q?=29=3A_Merge_issue_=2316439=3A_Fix_markup_in_example_for_stdtyp?= =?utf-8?b?ZXMu?= Message-ID: <3Xy7hG0hqSzPkT@mail.python.org> http://hg.python.org/cpython/rev/ce6fc4531d26 changeset: 80318:ce6fc4531d26 parent: 80315:e1e019b3d903 parent: 80317:65499860c6f8 user: Andrew Svetlov date: Thu Nov 08 17:27:53 2012 +0200 summary: Merge issue #16439: Fix markup in example for stdtypes. Thanks to Yongzhi Pan. files: Doc/library/stdtypes.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1832,11 +1832,11 @@ >>> import re >>> def titlecase(s): - return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", - lambda mo: mo.group(0)[0].upper() + - mo.group(0)[1:].lower(), - s) - + ... return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", + ... lambda mo: mo.group(0)[0].upper() + + ... mo.group(0)[1:].lower(), + ... s) + ... >>> titlecase("they're bill's friends.") "They're Bill's Friends." -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Thu Nov 8 16:29:19 2012 From: python-checkins at python.org (andrew.svetlov) Date: Thu, 8 Nov 2012 16:29:19 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogSXNzdWUgIzE2NDM5?= =?utf-8?q?=3A_Fix_markup_in_example_for_stdtypes=2E?= Message-ID: <3Xy7hH4DBHzPqg@mail.python.org> http://hg.python.org/cpython/rev/f068c3e7743d changeset: 80319:f068c3e7743d branch: 2.7 parent: 80307:d32d04edd371 user: Andrew Svetlov date: Thu Nov 08 17:29:02 2012 +0200 summary: Issue #16439: Fix markup in example for stdtypes. Thanks to Yongzhi Pan. files: Doc/library/stdtypes.rst | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -1253,11 +1253,11 @@ >>> import re >>> def titlecase(s): - return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", - lambda mo: mo.group(0)[0].upper() + - mo.group(0)[1:].lower(), - s) - + ... return re.sub(r"[A-Za-z]+('[A-Za-z]+)?", + ... lambda mo: mo.group(0)[0].upper() + + ... mo.group(0)[1:].lower(), + ... s) + ... >>> titlecase("they're bill's friends.") "They're Bill's Friends." -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 9 00:09:49 2012 From: python-checkins at python.org (ezio.melotti) Date: Fri, 9 Nov 2012 00:09:49 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMi43KTogIzE2NDQwOiBmaXgg?= =?utf-8?q?exception_type_and_clarify_example=2E?= Message-ID: <3XyKvd2lrwzQ1s@mail.python.org> http://hg.python.org/cpython/rev/8b181c75792f changeset: 80320:8b181c75792f branch: 2.7 user: Ezio Melotti date: Fri Nov 09 01:03:44 2012 +0200 summary: #16440: fix exception type and clarify example. files: Doc/library/stdtypes.rst | 27 +++++++++++++++++---------- 1 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2878,16 +2878,23 @@ Like function objects, methods objects support getting arbitrary attributes. However, since method attributes are actually stored on the underlying function object (``meth.im_func``), setting method attributes on either bound or unbound -methods is disallowed. Attempting to set a method attribute results in a -:exc:`TypeError` being raised. In order to set a method attribute, you need to -explicitly set it on the underlying function object:: - - class C: - def method(self): - pass - - c = C() - c.method.im_func.whoami = 'my name is c' +methods is disallowed. Attempting to set an attribute on a method results in +an :exc:`AttributeError` being raised. In order to set a method attribute, you +need to explicitly set it on the underlying function object:: + + >>> class C: + ... def method(self): + ... pass + ... + >>> c = C() + >>> c.method.whoami = 'my name is method' # can't set on the method + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'instancemethod' object has no attribute 'whoami' + >>> c.method.im_func.whoami = 'my name is method' + >>> c.method.whoami + 'my name is method' + See :ref:`types` for more information. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 9 00:09:50 2012 From: python-checkins at python.org (ezio.melotti) Date: Fri, 9 Nov 2012 00:09:50 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAoMy4yKTogIzE2NDQwOiBmaXgg?= =?utf-8?q?exception_type_and_clarify_example=2E?= Message-ID: <3XyKvf59YXzQ1s@mail.python.org> http://hg.python.org/cpython/rev/bb39ca6bcd7a changeset: 80321:bb39ca6bcd7a branch: 3.2 parent: 80316:aeb5c53a1d69 user: Ezio Melotti date: Fri Nov 09 01:08:25 2012 +0200 summary: #16440: fix exception type and clarify example. files: Doc/library/stdtypes.rst | 26 ++++++++++++++++---------- 1 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -2659,16 +2659,22 @@ Like function objects, bound method objects support getting arbitrary attributes. However, since method attributes are actually stored on the underlying function object (``meth.__func__``), setting method attributes on -bound methods is disallowed. Attempting to set a method attribute results in a -:exc:`TypeError` being raised. In order to set a method attribute, you need to -explicitly set it on the underlying function object:: - - class C: - def method(self): - pass - - c = C() - c.method.__func__.whoami = 'my name is c' +bound methods is disallowed. Attempting to set an attribute on a method +results in an :exc:`AttributeError` being raised. In order to set a method +attribute, you need to explicitly set it on the underlying function object:: + + >>> class C: + ... def method(self): + ... pass + ... + >>> c = C() + >>> c.method.whoami = 'my name is method' # can't set on the method + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'method' object has no attribute 'whoami' + >>> c.method.__func__.whoami = 'my name is method' + >>> c.method.whoami + 'my name is method' See :ref:`types` for more information. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 9 00:09:52 2012 From: python-checkins at python.org (ezio.melotti) Date: Fri, 9 Nov 2012 00:09:52 +0100 (CET) Subject: [Python-checkins] =?utf-8?b?Y3B5dGhvbiAobWVyZ2UgMy4yIC0+IDMuMyk6?= =?utf-8?q?_=2316440=3A_merge_with_3=2E2=2E?= Message-ID: <3XyKvh0XRKzQ3l@mail.python.org> http://hg.python.org/cpython/rev/8c7f2f6f3375 changeset: 80322:8c7f2f6f3375 branch: 3.3 parent: 80317:65499860c6f8 parent: 80321:bb39ca6bcd7a user: Ezio Melotti date: Fri Nov 09 01:09:10 2012 +0200 summary: #16440: merge with 3.2. files: Doc/library/stdtypes.rst | 26 ++++++++++++++++---------- 1 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3343,16 +3343,22 @@ Like function objects, bound method objects support getting arbitrary attributes. However, since method attributes are actually stored on the underlying function object (``meth.__func__``), setting method attributes on -bound methods is disallowed. Attempting to set a method attribute results in a -:exc:`TypeError` being raised. In order to set a method attribute, you need to -explicitly set it on the underlying function object:: - - class C: - def method(self): - pass - - c = C() - c.method.__func__.whoami = 'my name is c' +bound methods is disallowed. Attempting to set an attribute on a method +results in an :exc:`AttributeError` being raised. In order to set a method +attribute, you need to explicitly set it on the underlying function object:: + + >>> class C: + ... def method(self): + ... pass + ... + >>> c = C() + >>> c.method.whoami = 'my name is method' # can't set on the method + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'method' object has no attribute 'whoami' + >>> c.method.__func__.whoami = 'my name is method' + >>> c.method.whoami + 'my name is method' See :ref:`types` for more information. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 9 00:09:53 2012 From: python-checkins at python.org (ezio.melotti) Date: Fri, 9 Nov 2012 00:09:53 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?cpython_=28merge_3=2E3_-=3E_default?= =?utf-8?b?KTogIzE2NDQwOiBtZXJnZSB3aXRoIDMuMy4=?= Message-ID: <3XyKvj2rJjzQ0g@mail.python.org> http://hg.python.org/cpython/rev/d170844a363f changeset: 80323:d170844a363f parent: 80318:ce6fc4531d26 parent: 80322:8c7f2f6f3375 user: Ezio Melotti date: Fri Nov 09 01:09:27 2012 +0200 summary: #16440: merge with 3.3. files: Doc/library/stdtypes.rst | 26 ++++++++++++++++---------- 1 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -3343,16 +3343,22 @@ Like function objects, bound method objects support getting arbitrary attributes. However, since method attributes are actually stored on the underlying function object (``meth.__func__``), setting method attributes on -bound methods is disallowed. Attempting to set a method attribute results in a -:exc:`TypeError` being raised. In order to set a method attribute, you need to -explicitly set it on the underlying function object:: - - class C: - def method(self): - pass - - c = C() - c.method.__func__.whoami = 'my name is c' +bound methods is disallowed. Attempting to set an attribute on a method +results in an :exc:`AttributeError` being raised. In order to set a method +attribute, you need to explicitly set it on the underlying function object:: + + >>> class C: + ... def method(self): + ... pass + ... + >>> c = C() + >>> c.method.whoami = 'my name is method' # can't set on the method + Traceback (most recent call last): + File "", line 1, in + AttributeError: 'method' object has no attribute 'whoami' + >>> c.method.__func__.whoami = 'my name is method' + >>> c.method.whoami + 'my name is method' See :ref:`types` for more information. -- Repository URL: http://hg.python.org/cpython From python-checkins at python.org Fri Nov 9 01:08:43 2012 From: python-checkins at python.org (brett.cannon) Date: Fri, 9 Nov 2012 01:08:43 +0100 (CET) Subject: [Python-checkins] =?utf-8?q?benchmarks=3A_Update_mako=5Fv2_to_use?= =?utf-8?b?IE1ha28gMC43LjMu?= Message-ID: <3XyMCb23cGzPlf@mail.python.org> http://hg.python.org/benchmarks/rev/d456cee3fd8a changeset: 191:d456cee3fd8a user: Brett Cannon date: Thu Nov 08 19:07:59 2012 -0500 summary: Update mako_v2 to use Mako 0.7.3. Once speed.python.org is up and running and relying on historic data then upgrading library versions probably should be avoided. files: lib/Mako-0.7.3/CHANGES | 847 ++++++ lib/Mako-0.7.3/LICENSE | 20 + lib/Mako-0.7.3/MANIFEST.in | 11 + lib/Mako-0.7.3/Mako.egg-info/PKG-INFO | 71 + lib/Mako-0.7.3/Mako.egg-info/SOURCES.txt | 171 + lib/Mako-0.7.3/Mako.egg-info/dependency_links.txt | 1 + lib/Mako-0.7.3/Mako.egg-info/entry_points.txt | 14 + lib/Mako-0.7.3/Mako.egg-info/not-zip-safe | 1 + lib/Mako-0.7.3/Mako.egg-info/requires.txt | 4 + lib/Mako-0.7.3/Mako.egg-info/top_level.txt | 1 + lib/Mako-0.7.3/PKG-INFO | 71 + lib/Mako-0.7.3/README.rst | 52 + lib/Mako-0.7.3/distribute_setup.py | 485 +++ lib/Mako-0.7.3/doc/_sources/caching.txt | 393 +++ lib/Mako-0.7.3/doc/_sources/defs.txt | 622 +++++ lib/Mako-0.7.3/doc/_sources/filtering.txt | 344 ++ lib/Mako-0.7.3/doc/_sources/index.txt | 22 + lib/Mako-0.7.3/doc/_sources/inheritance.txt | 534 ++++ lib/Mako-0.7.3/doc/_sources/namespaces.txt | 349 ++ lib/Mako-0.7.3/doc/_sources/runtime.txt | 448 +++ lib/Mako-0.7.3/doc/_sources/syntax.txt | 469 +++ lib/Mako-0.7.3/doc/_sources/unicode.txt | 345 ++ lib/Mako-0.7.3/doc/_sources/usage.txt | 520 ++++ lib/Mako-0.7.3/doc/_static/basic.css | 540 ++++ lib/Mako-0.7.3/doc/_static/comment-bright.png | Bin lib/Mako-0.7.3/doc/_static/comment-close.png | Bin lib/Mako-0.7.3/doc/_static/comment.png | Bin lib/Mako-0.7.3/doc/_static/default.css | 256 ++ lib/Mako-0.7.3/doc/_static/docs.css | 438 +++ lib/Mako-0.7.3/doc/_static/doctools.js | 247 + lib/Mako-0.7.3/doc/_static/down-pressed.png | Bin lib/Mako-0.7.3/doc/_static/down.png | Bin lib/Mako-0.7.3/doc/_static/file.png | Bin lib/Mako-0.7.3/doc/_static/jquery.js | 154 + lib/Mako-0.7.3/doc/_static/makoLogo.png | Bin lib/Mako-0.7.3/doc/_static/minus.png | Bin lib/Mako-0.7.3/doc/_static/plus.png | Bin lib/Mako-0.7.3/doc/_static/pygments.css | 62 + lib/Mako-0.7.3/doc/_static/searchtools.js | 560 ++++ lib/Mako-0.7.3/doc/_static/sidebar.js | 151 + lib/Mako-0.7.3/doc/_static/site.css | 86 + lib/Mako-0.7.3/doc/_static/underscore.js | 23 + lib/Mako-0.7.3/doc/_static/up-pressed.png | Bin lib/Mako-0.7.3/doc/_static/up.png | Bin lib/Mako-0.7.3/doc/_static/websupport.js | 808 ++++++ lib/Mako-0.7.3/doc/build/Makefile | 137 + lib/Mako-0.7.3/doc/build/builder/__init__.py | 0 lib/Mako-0.7.3/doc/build/builder/builders.py | 97 + lib/Mako-0.7.3/doc/build/builder/util.py | 12 + lib/Mako-0.7.3/doc/build/caching.rst | 393 +++ lib/Mako-0.7.3/doc/build/conf.py | 287 ++ lib/Mako-0.7.3/doc/build/defs.rst | 622 +++++ lib/Mako-0.7.3/doc/build/filtering.rst | 344 ++ lib/Mako-0.7.3/doc/build/index.rst | 22 + lib/Mako-0.7.3/doc/build/inheritance.rst | 534 ++++ lib/Mako-0.7.3/doc/build/namespaces.rst | 349 ++ lib/Mako-0.7.3/doc/build/runtime.rst | 448 +++ lib/Mako-0.7.3/doc/build/static/docs.css | 438 +++ lib/Mako-0.7.3/doc/build/static/makoLogo.png | Bin lib/Mako-0.7.3/doc/build/static/site.css | 86 + lib/Mako-0.7.3/doc/build/syntax.rst | 469 +++ lib/Mako-0.7.3/doc/build/templates/base.mako | 60 + lib/Mako-0.7.3/doc/build/templates/genindex.mako | 77 + lib/Mako-0.7.3/doc/build/templates/layout.mako | 199 + lib/Mako-0.7.3/doc/build/templates/page.mako | 2 + lib/Mako-0.7.3/doc/build/templates/rtd_layout.mako | 174 + lib/Mako-0.7.3/doc/build/templates/search.mako | 25 + lib/Mako-0.7.3/doc/build/unicode.rst | 345 ++ lib/Mako-0.7.3/doc/build/usage.rst | 520 ++++ lib/Mako-0.7.3/doc/caching.html | 779 ++++++ lib/Mako-0.7.3/doc/defs.html | 728 +++++ lib/Mako-0.7.3/doc/filtering.html | 478 +++ lib/Mako-0.7.3/doc/genindex.html | 916 +++++++ lib/Mako-0.7.3/doc/index.html | 230 + lib/Mako-0.7.3/doc/inheritance.html | 673 +++++ lib/Mako-0.7.3/doc/namespaces.html | 649 +++++ lib/Mako-0.7.3/doc/runtime.html | 710 +++++ lib/Mako-0.7.3/doc/search.html | 162 + lib/Mako-0.7.3/doc/searchindex.js | 1 + lib/Mako-0.7.3/doc/syntax.html | 596 ++++ lib/Mako-0.7.3/doc/unicode.html | 476 +++ lib/Mako-0.7.3/doc/usage.html | 1057 ++++++++ lib/Mako-0.7.3/examples/bench/basic.py | 191 + lib/Mako-0.7.3/examples/bench/cheetah/footer.tmpl | 2 + lib/Mako-0.7.3/examples/bench/cheetah/header.tmpl | 5 + lib/Mako-0.7.3/examples/bench/cheetah/template.tmpl | 31 + lib/Mako-0.7.3/examples/bench/django/templatetags/__init__.py | 0 lib/Mako-0.7.3/examples/bench/django/templatetags/bench.py | 8 + lib/Mako-0.7.3/examples/bench/kid/base.kid | 15 + lib/Mako-0.7.3/examples/bench/kid/template.kid | 22 + lib/Mako-0.7.3/examples/bench/myghty/base.myt | 29 + lib/Mako-0.7.3/examples/bench/myghty/template.myt | 30 + lib/Mako-0.7.3/examples/wsgi/run_wsgi.py | 78 + lib/Mako-0.7.3/mako/__init__.py | 9 + lib/Mako-0.7.3/mako/_ast_util.py | 839 ++++++ lib/Mako-0.7.3/mako/ast.py | 151 + lib/Mako-0.7.3/mako/cache.py | 236 + lib/Mako-0.7.3/mako/codegen.py | 1215 +++++++++ lib/Mako-0.7.3/mako/exceptions.py | 362 ++ lib/Mako-0.7.3/mako/ext/__init__.py | 0 lib/Mako-0.7.3/mako/ext/autohandler.py | 65 + lib/Mako-0.7.3/mako/ext/babelplugin.py | 132 + lib/Mako-0.7.3/mako/ext/beaker_cache.py | 70 + lib/Mako-0.7.3/mako/ext/preprocessors.py | 20 + lib/Mako-0.7.3/mako/ext/pygmentplugin.py | 122 + lib/Mako-0.7.3/mako/ext/turbogears.py | 57 + lib/Mako-0.7.3/mako/filters.py | 191 + lib/Mako-0.7.3/mako/lexer.py | 442 +++ lib/Mako-0.7.3/mako/lookup.py | 354 ++ lib/Mako-0.7.3/mako/parsetree.py | 596 ++++ lib/Mako-0.7.3/mako/pygen.py | 283 ++ lib/Mako-0.7.3/mako/pyparser.py | 551 ++++ lib/Mako-0.7.3/mako/runtime.py | 841 ++++++ lib/Mako-0.7.3/mako/template.py | 650 +++++ lib/Mako-0.7.3/mako/util.py | 438 +++ lib/Mako-0.7.3/scripts/mako-render | 46 + lib/Mako-0.7.3/setup.cfg | 5 + lib/Mako-0.7.3/setup.py | 62 + lib/Mako-0.7.3/test/__init__.py | 145 + lib/Mako-0.7.3/test/foo/__init__.py | 0 lib/Mako-0.7.3/test/foo/test_ns.py | 7 + lib/Mako-0.7.3/test/sample_module_namespace.py | 7 + lib/Mako-0.7.3/test/templates/badbom.html | 2 + lib/Mako-0.7.3/test/templates/bom.html | 1 + lib/Mako-0.7.3/test/templates/bommagic.html | 2 + lib/Mako-0.7.3/test/templates/chs_unicode.html | 11 + lib/Mako-0.7.3/test/templates/chs_unicode_py3k.html | 11 + lib/Mako-0.7.3/test/templates/chs_utf8.html | 17 + lib/Mako-0.7.3/test/templates/crlf.html | 19 + lib/Mako-0.7.3/test/templates/foo/modtest.html.py | 25 + lib/Mako-0.7.3/test/templates/gettext.mako | 89 + lib/Mako-0.7.3/test/templates/index.html | 1 + lib/Mako-0.7.3/test/templates/internationalization.html | 920 +++++++ lib/Mako-0.7.3/test/templates/modtest.html | 1 + lib/Mako-0.7.3/test/templates/othersubdir/foo.html | 0 lib/Mako-0.7.3/test/templates/read_unicode.html | 10 + lib/Mako-0.7.3/test/templates/read_unicode_py3k.html | 10 + lib/Mako-0.7.3/test/templates/runtimeerr.html | 4 + lib/Mako-0.7.3/test/templates/runtimeerr_py3k.html | 4 + lib/Mako-0.7.3/test/templates/subdir/foo/modtest.html.py | 25 + lib/Mako-0.7.3/test/templates/subdir/incl.html | 2 + lib/Mako-0.7.3/test/templates/subdir/index.html | 3 + lib/Mako-0.7.3/test/templates/subdir/modtest.html | 1 + lib/Mako-0.7.3/test/templates/unicode.html | 2 + lib/Mako-0.7.3/test/templates/unicode_arguments.html | 10 + lib/Mako-0.7.3/test/templates/unicode_arguments_py3k.html | 10 + lib/Mako-0.7.3/test/templates/unicode_code.html | 7 + lib/Mako-0.7.3/test/templates/unicode_code_py3k.html | 7 + lib/Mako-0.7.3/test/templates/unicode_expr.html | 2 + lib/Mako-0.7.3/test/templates/unicode_expr_py3k.html | 2 + lib/Mako-0.7.3/test/templates/unicode_runtime_error.html | 2 + lib/Mako-0.7.3/test/templates/unicode_syntax_error.html | 2 + lib/Mako-0.7.3/test/test_ast.py | 334 ++ lib/Mako-0.7.3/test/test_babelplugin.py | 44 + lib/Mako-0.7.3/test/test_block.py | 569 ++++ lib/Mako-0.7.3/test/test_cache.py | 557 ++++ lib/Mako-0.7.3/test/test_call.py | 515 ++++ lib/Mako-0.7.3/test/test_decorators.py | 110 + lib/Mako-0.7.3/test/test_def.py | 678 +++++ lib/Mako-0.7.3/test/test_exceptions.py | 300 ++ lib/Mako-0.7.3/test/test_filters.py | 335 ++ lib/Mako-0.7.3/test/test_inheritance.py | 350 ++ lib/Mako-0.7.3/test/test_lexer.py | 871 +++++++ lib/Mako-0.7.3/test/test_lookup.py | 104 + lib/Mako-0.7.3/test/test_loop.py | 295 ++ lib/Mako-0.7.3/test/test_lru.py | 111 + lib/Mako-0.7.3/test/test_namespace.py | 792 ++++++ lib/Mako-0.7.3/test/test_pygen.py | 252 ++ lib/Mako-0.7.3/test/test_template.py | 1242 ++++++++++ lib/Mako-0.7.3/test/test_tgplugin.py | 42 + lib/Mako-0.7.3/test/test_util.py | 50 + lib/Mako-0.7.3/test/util.py | 7 + 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 | 620 ---- 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 | 447 --- lib/mako-0.7.2/doc/_sources/syntax.txt | 469 --- lib/mako-0.7.2/doc/_sources/unicode.txt | 344 -- 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 | 620 ---- 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 | 447 --- 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 | 344 -- 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 - perf.py | 2 +- 345 files changed, 39283 insertions(+), 39130 deletions(-) diff --git a/lib/Mako-0.7.3/CHANGES b/lib/Mako-0.7.3/CHANGES new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/CHANGES @@ -0,0 +1,847 @@ + +0.7.3 +- [bug] legacy_html_escape function, used when + Markupsafe isn't installed, was using an inline-compiled + regexp which causes major slowdowns on Python 3.3; + is now precompiled. + +- [bug] AST supporting now supports tuple-packed + function arguments inside pure-python def + or lambda expressions. [ticket:201] + +- [bug] Fixed Py3K bug in the Babel extension. + +- [bug] Fixed the "filter" attribute of the + <%text> tag so that it pulls locally specified + identifiers from the context the same + way as that of <%block> and <%filter>. + +- [bug] Fixed bug in plugin loader to correctly + raise exception when non-existent plugin + is specified. + +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.3/LICENSE b/lib/Mako-0.7.3/LICENSE new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/MANIFEST.in b/lib/Mako-0.7.3/MANIFEST.in new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/Mako.egg-info/PKG-INFO b/lib/Mako-0.7.3/Mako.egg-info/PKG-INFO new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/Mako.egg-info/PKG-INFO @@ -0,0 +1,71 @@ +Metadata-Version: 1.0 +Name: Mako +Version: 0.7.3 +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.3/Mako.egg-info/SOURCES.txt b/lib/Mako-0.7.3/Mako.egg-info/SOURCES.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/Mako.egg-info/dependency_links.txt b/lib/Mako-0.7.3/Mako.egg-info/dependency_links.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/Mako.egg-info/dependency_links.txt @@ -0,0 +1,1 @@ + diff --git a/lib/Mako-0.7.3/Mako.egg-info/entry_points.txt b/lib/Mako-0.7.3/Mako.egg-info/entry_points.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/Mako.egg-info/not-zip-safe b/lib/Mako-0.7.3/Mako.egg-info/not-zip-safe new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/Mako.egg-info/not-zip-safe @@ -0,0 +1,1 @@ + diff --git a/lib/Mako-0.7.3/Mako.egg-info/requires.txt b/lib/Mako-0.7.3/Mako.egg-info/requires.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/Mako.egg-info/top_level.txt b/lib/Mako-0.7.3/Mako.egg-info/top_level.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/Mako.egg-info/top_level.txt @@ -0,0 +1,1 @@ +mako diff --git a/lib/Mako-0.7.3/PKG-INFO b/lib/Mako-0.7.3/PKG-INFO new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/PKG-INFO @@ -0,0 +1,71 @@ +Metadata-Version: 1.0 +Name: Mako +Version: 0.7.3 +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.3/README.rst b/lib/Mako-0.7.3/README.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/distribute_setup.py b/lib/Mako-0.7.3/distribute_setup.py new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/caching.txt b/lib/Mako-0.7.3/doc/_sources/caching.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/defs.txt b/lib/Mako-0.7.3/doc/_sources/defs.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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 ``
'; + + 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.3/doc/build/Makefile b/lib/Mako-0.7.3/doc/build/Makefile new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/builder/__init__.py b/lib/Mako-0.7.3/doc/build/builder/__init__.py new file mode 100644 diff --git a/lib/Mako-0.7.3/doc/build/builder/builders.py b/lib/Mako-0.7.3/doc/build/builder/builders.py new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/builder/util.py b/lib/Mako-0.7.3/doc/build/builder/util.py new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/caching.rst b/lib/Mako-0.7.3/doc/build/caching.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/conf.py b/lib/Mako-0.7.3/doc/build/conf.py new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/defs.rst b/lib/Mako-0.7.3/doc/build/defs.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/filtering.rst b/lib/Mako-0.7.3/doc/build/filtering.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/index.rst b/lib/Mako-0.7.3/doc/build/index.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/inheritance.rst b/lib/Mako-0.7.3/doc/build/inheritance.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/namespaces.rst b/lib/Mako-0.7.3/doc/build/namespaces.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/runtime.rst b/lib/Mako-0.7.3/doc/build/runtime.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/static/docs.css b/lib/Mako-0.7.3/doc/build/static/docs.css new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/static/makoLogo.png b/lib/Mako-0.7.3/doc/build/static/makoLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c43c087eb48ebfc2223b76cf3df2fa7868c2a72b GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/build/static/site.css b/lib/Mako-0.7.3/doc/build/static/site.css new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/build/static/site.css @@ -0,0 +1,86 @@ +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; +} +.slogan { + margin-top:10px; +} +#gittip_nav { + float:right; + margin:10px 0px 0px 0px; +} + +.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.3/doc/build/syntax.rst b/lib/Mako-0.7.3/doc/build/syntax.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/templates/base.mako b/lib/Mako-0.7.3/doc/build/templates/base.mako new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/build/templates/base.mako @@ -0,0 +1,60 @@ + + + + +<%block name="head_title">Mako Templates for Python</%block> +<%block name="headers"> + + + + + + +
    + + + + +
    + + ${next.body()} +
    +<%block name="footer"> +
    + + + +
    +
    + + diff --git a/lib/Mako-0.7.3/doc/build/templates/genindex.mako b/lib/Mako-0.7.3/doc/build/templates/genindex.mako new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/templates/layout.mako b/lib/Mako-0.7.3/doc/build/templates/layout.mako new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/templates/page.mako b/lib/Mako-0.7.3/doc/build/templates/page.mako new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/templates/rtd_layout.mako b/lib/Mako-0.7.3/doc/build/templates/rtd_layout.mako new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/templates/search.mako b/lib/Mako-0.7.3/doc/build/templates/search.mako new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/unicode.rst b/lib/Mako-0.7.3/doc/build/unicode.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/build/usage.rst b/lib/Mako-0.7.3/doc/build/usage.rst new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/caching.html b/lib/Mako-0.7.3/doc/caching.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/caching.html @@ -0,0 +1,779 @@ + + + + + + + Caching + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/defs.html b/lib/Mako-0.7.3/doc/defs.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/defs.html @@ -0,0 +1,728 @@ + + + + + + + Defs and Blocks + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/filtering.html b/lib/Mako-0.7.3/doc/filtering.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/filtering.html @@ -0,0 +1,478 @@ + + + + + + + Filtering and Buffering + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/genindex.html b/lib/Mako-0.7.3/doc/genindex.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/genindex.html @@ -0,0 +1,916 @@ + + + + + + + Index + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/index.html b/lib/Mako-0.7.3/doc/index.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/index.html @@ -0,0 +1,230 @@ + + + + + + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 Documentation + +

    + + Table of Contents + +

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

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/namespaces.html b/lib/Mako-0.7.3/doc/namespaces.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/namespaces.html @@ -0,0 +1,649 @@ + + + + + + + Namespaces + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/runtime.html b/lib/Mako-0.7.3/doc/runtime.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/runtime.html @@ -0,0 +1,710 @@ + + + + + + + The Mako Runtime Environment + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/search.html b/lib/Mako-0.7.3/doc/search.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/search.html @@ -0,0 +1,162 @@ + + + + + + + Search + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 Documentation + ? + Search + + +

    + + Search + +

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

    Enter Search Terms:

    + +
    + +
    + + + +
    + +
    + + + +
    + +
    + + +
    + + + + + +
    +
    + + diff --git a/lib/Mako-0.7.3/doc/searchindex.js b/lib/Mako-0.7.3/doc/searchindex.js new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/syntax.html b/lib/Mako-0.7.3/doc/syntax.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/syntax.html @@ -0,0 +1,596 @@ + + + + + + + Syntax + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/unicode.html b/lib/Mako-0.7.3/doc/unicode.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/unicode.html @@ -0,0 +1,476 @@ + + + + + + + The Unicode Chapter + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/doc/usage.html b/lib/Mako-0.7.3/doc/usage.html new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/doc/usage.html @@ -0,0 +1,1057 @@ + + + + + + + Usage + — + Mako 0.7.3 Documentation + + + + + + + + + + + + + + + + + + + + +
    +
    + + +
    + Hyperfast and lightweight templating for the Python platform. +
    + + +
    + + + +
    + + + + + + + + + + + +
    + + + +
    +

    Mako 0.7.3 Documentation

    + + + +
    + Release: 0.7.3 + +
    + +
    + +
    + + +
    + Mako 0.7.3 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.3/examples/bench/basic.py b/lib/Mako-0.7.3/examples/bench/basic.py new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/examples/bench/cheetah/footer.tmpl b/lib/Mako-0.7.3/examples/bench/cheetah/footer.tmpl new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/examples/bench/cheetah/footer.tmpl @@ -0,0 +1,2 @@ + diff --git a/lib/Mako-0.7.3/examples/bench/cheetah/header.tmpl b/lib/Mako-0.7.3/examples/bench/cheetah/header.tmpl new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/examples/bench/cheetah/header.tmpl @@ -0,0 +1,5 @@ + + + diff --git a/lib/Mako-0.7.3/examples/bench/cheetah/template.tmpl b/lib/Mako-0.7.3/examples/bench/cheetah/template.tmpl new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/examples/bench/django/templatetags/__init__.py b/lib/Mako-0.7.3/examples/bench/django/templatetags/__init__.py new file mode 100644 diff --git a/lib/Mako-0.7.3/examples/bench/django/templatetags/bench.py b/lib/Mako-0.7.3/examples/bench/django/templatetags/bench.py new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/examples/bench/kid/base.kid b/lib/Mako-0.7.3/examples/bench/kid/base.kid new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/examples/bench/kid/base.kid @@ -0,0 +1,15 @@ + + +

    + Hello, ${name}! +

    + + + + ${item} + '; - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/Makefile +++ /dev/null @@ -1,137 +0,0 @@ -# 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 deleted 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/builder/builders.py +++ /dev/null @@ -1,97 +0,0 @@ -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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/builder/util.py +++ /dev/null @@ -1,12 +0,0 @@ -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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/caching.rst +++ /dev/null @@ -1,393 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/conf.py +++ /dev/null @@ -1,287 +0,0 @@ -# -*- 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/defs.rst +++ /dev/null @@ -1,622 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/filtering.rst +++ /dev/null @@ -1,344 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/inheritance.rst +++ /dev/null @@ -1,534 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/namespaces.rst +++ /dev/null @@ -1,349 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/runtime.rst +++ /dev/null @@ -1,448 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/static/docs.css +++ /dev/null @@ -1,438 +0,0 @@ -/* 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 deleted file mode 100644 Binary file lib/mako-0.7.2/doc/build/static/makoLogo.png has changed diff --git a/lib/mako-0.7.2/doc/build/static/site.css b/lib/mako-0.7.2/doc/build/static/site.css deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/static/site.css +++ /dev/null @@ -1,82 +0,0 @@ -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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/syntax.rst +++ /dev/null @@ -1,469 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/templates/base.mako +++ /dev/null @@ -1,51 +0,0 @@ - - - - -<%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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/templates/genindex.mako +++ /dev/null @@ -1,77 +0,0 @@ -<%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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/templates/layout.mako +++ /dev/null @@ -1,199 +0,0 @@ -## 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/templates/page.mako +++ /dev/null @@ -1,2 +0,0 @@ -<%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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/templates/rtd_layout.mako +++ /dev/null @@ -1,174 +0,0 @@ - - -<%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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/templates/search.mako +++ /dev/null @@ -1,25 +0,0 @@ -<%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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/unicode.rst +++ /dev/null @@ -1,345 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/build/usage.rst +++ /dev/null @@ -1,520 +0,0 @@ -.. _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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/caching.html +++ /dev/null @@ -1,777 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/defs.html +++ /dev/null @@ -1,726 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/filtering.html +++ /dev/null @@ -1,476 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/genindex.html +++ /dev/null @@ -1,914 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/index.html +++ /dev/null @@ -1,228 +0,0 @@ - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/inheritance.html +++ /dev/null @@ -1,671 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/namespaces.html +++ /dev/null @@ -1,647 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/runtime.html +++ /dev/null @@ -1,708 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/search.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/searchindex.js +++ /dev/null @@ -1,1 +0,0 @@ -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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/syntax.html +++ /dev/null @@ -1,594 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/unicode.html +++ /dev/null @@ -1,474 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/doc/usage.html +++ /dev/null @@ -1,1055 +0,0 @@ - - - - - - - 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 deleted file mode 100644 --- a/lib/mako-0.7.2/examples/bench/basic.py +++ /dev/null @@ -1,191 +0,0 @@ -# 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 deleted file mode 100644 --- a/lib/mako-0.7.2/examples/bench/cheetah/footer.tmpl +++ /dev/null @@ -1,2 +0,0 @@ - diff --git a/lib/mako-0.7.2/examples/bench/cheetah/header.tmpl b/lib/mako-0.7.2/examples/bench/cheetah/header.tmpl deleted file mode 100644 --- a/lib/mako-0.7.2/examples/bench/cheetah/header.tmpl +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/lib/mako-0.7.2/examples/bench/cheetah/template.tmpl b/lib/mako-0.7.2/examples/bench/cheetah/template.tmpl deleted file mode 100644 --- a/lib/mako-0.7.2/examples/bench/cheetah/template.tmpl +++ /dev/null @@ -1,31 +0,0 @@ - - - - ${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 deleted 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 deleted file mode 100644 --- a/lib/mako-0.7.2/examples/bench/django/templatetags/bench.py +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 --- a/lib/mako-0.7.2/examples/bench/kid/base.kid +++ /dev/null @@ -1,15 +0,0 @@ - - -

    - Hello, ${name}! -

    - - - - ${item} -
    `` +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.3/doc/_sources/filtering.txt b/lib/Mako-0.7.3/doc/_sources/filtering.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/index.txt b/lib/Mako-0.7.3/doc/_sources/index.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/inheritance.txt b/lib/Mako-0.7.3/doc/_sources/inheritance.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/namespaces.txt b/lib/Mako-0.7.3/doc/_sources/namespaces.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/runtime.txt b/lib/Mako-0.7.3/doc/_sources/runtime.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/syntax.txt b/lib/Mako-0.7.3/doc/_sources/syntax.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/unicode.txt b/lib/Mako-0.7.3/doc/_sources/unicode.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_sources/usage.txt b/lib/Mako-0.7.3/doc/_sources/usage.txt new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_static/basic.css b/lib/Mako-0.7.3/doc/_static/basic.css new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_static/comment-bright.png b/lib/Mako-0.7.3/doc/_static/comment-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..551517b8c83b76f734ff791f847829a760ad1903 GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/comment-close.png b/lib/Mako-0.7.3/doc/_static/comment-close.png new file mode 100644 index 0000000000000000000000000000000000000000..09b54be46da3f0d4a5061da289dc91d8a2cdbc9c GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/comment.png b/lib/Mako-0.7.3/doc/_static/comment.png new file mode 100644 index 0000000000000000000000000000000000000000..92feb52b8824c6b0f59b658b1196c61de9162a95 GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/default.css b/lib/Mako-0.7.3/doc/_static/default.css new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_static/docs.css b/lib/Mako-0.7.3/doc/_static/docs.css new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_static/doctools.js b/lib/Mako-0.7.3/doc/_static/doctools.js new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_static/down-pressed.png b/lib/Mako-0.7.3/doc/_static/down-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..6f7ad782782e4f8e39b0c6e15c7344700cdd2527 GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/down.png b/lib/Mako-0.7.3/doc/_static/down.png new file mode 100644 index 0000000000000000000000000000000000000000..3003a88770de3977d47a2ba69893436a2860f9e7 GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/file.png b/lib/Mako-0.7.3/doc/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..d18082e397e7e54f20721af768c4c2983258f1b4 GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/jquery.js b/lib/Mako-0.7.3/doc/_static/jquery.js new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_static/makoLogo.png b/lib/Mako-0.7.3/doc/_static/makoLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..c43c087eb48ebfc2223b76cf3df2fa7868c2a72b GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/minus.png b/lib/Mako-0.7.3/doc/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..da1c5620d10c047525a467a425abe9ff5269cfc2 GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/plus.png b/lib/Mako-0.7.3/doc/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..b3cb37425ea68b39ffa7b2e5fb69161275a87541 GIT binary patch [stripped] diff --git a/lib/Mako-0.7.3/doc/_static/pygments.css b/lib/Mako-0.7.3/doc/_static/pygments.css new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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.3/doc/_static/searchtools.js b/lib/Mako-0.7.3/doc/_static/searchtools.js new file mode 100644 --- /dev/null +++ b/lib/Mako-0.7.3/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 ▿\ + \ +

      \ + \ + \ + \ + \ + \ +
      \ +