[Python-checkins] r60579 - in python/branches/release25-maint: Lib/test/test_trace.py Misc/NEWS Python/compile.c

Brett Cannon brett at python.org
Tue Feb 5 00:41:28 CET 2008


It looks like this broke test_compile.

-Brett

On Feb 4, 2008 2:34 PM, amaury.forgeotdarc <python-checkins at python.org> wrote:
> Author: amaury.forgeotdarc
> Date: Mon Feb  4 23:34:57 2008
> New Revision: 60579
>
> Modified:
>    python/branches/release25-maint/Lib/test/test_trace.py
>    python/branches/release25-maint/Misc/NEWS
>    python/branches/release25-maint/Python/compile.c
> Log:
> backport of r60575 (issue #1750076): Debugger did not step on every iteration of a while statement.
>
> The mapping between bytecode offsets and source lines (lnotab) did not contain
> an entry for the beginning of the loop.
>
> Now it does, and the lnotab can be a bit larger:
> in particular, several statements on the same line generate several entries.
> However, this does not bother the settrace function, which will trigger only
> one 'line' event.
>
> The lnotab seems to be exactly the same as with python2.4.
>
>
> Modified: python/branches/release25-maint/Lib/test/test_trace.py
> ==============================================================================
> --- python/branches/release25-maint/Lib/test/test_trace.py      (original)
> +++ python/branches/release25-maint/Lib/test/test_trace.py      Mon Feb  4 23:34:57 2008
> @@ -252,14 +252,16 @@
>                  "\n".join(difflib.ndiff([str(x) for x in expected_events],
>                                          [str(x) for x in events])))
>
> -
> -    def run_test(self, func):
> +    def run_and_compare(self, func, events):
>          tracer = Tracer()
>          sys.settrace(tracer.trace)
>          func()
>          sys.settrace(None)
>          self.compare_events(func.func_code.co_firstlineno,
> -                            tracer.events, func.events)
> +                            tracer.events, events)
> +
> +    def run_test(self, func):
> +        self.run_and_compare(func, func.events)
>
>      def run_test2(self, func):
>          tracer = Tracer()
> @@ -307,6 +309,49 @@
>          self.compare_events(generator_example.func_code.co_firstlineno,
>                              tracer.events, generator_example.events)
>
> +    def test_14_onliner_if(self):
> +        def onliners():
> +            if True: False
> +            else: True
> +            return 0
> +        self.run_and_compare(
> +            onliners,
> +            [(0, 'call'),
> +             (1, 'line'),
> +             (3, 'line'),
> +             (3, 'return')])
> +
> +    def test_15_loops(self):
> +        # issue1750076: "while" expression is skipped by debugger
> +        def for_example():
> +            for x in range(2):
> +                pass
> +        self.run_and_compare(
> +            for_example,
> +            [(0, 'call'),
> +             (1, 'line'),
> +             (2, 'line'),
> +             (1, 'line'),
> +             (2, 'line'),
> +             (1, 'line'),
> +             (1, 'return')])
> +
> +        def while_example():
> +            # While expression should be traced on every loop
> +            x = 2
> +            while x > 0:
> +                x -= 1
> +        self.run_and_compare(
> +            while_example,
> +            [(0, 'call'),
> +             (2, 'line'),
> +             (3, 'line'),
> +             (4, 'line'),
> +             (3, 'line'),
> +             (4, 'line'),
> +             (3, 'line'),
> +             (3, 'return')])
> +
>  class RaisingTraceFuncTestCase(unittest.TestCase):
>      def trace(self, frame, event, arg):
>          """A trace function that raises an exception in response to a
>
> Modified: python/branches/release25-maint/Misc/NEWS
> ==============================================================================
> --- python/branches/release25-maint/Misc/NEWS   (original)
> +++ python/branches/release25-maint/Misc/NEWS   Mon Feb  4 23:34:57 2008
> @@ -80,6 +80,10 @@
>  Library
>  -------
>
> +- #175006: The debugger used to skip the condition of a "while" statement
> +  after the first iteration. Now it correctly steps on the expression, and
> +  breakpoints on the "while" statement are honored on each loop.
> +
>  - The ctypes int types did not accept objects implementing
>    __int__() in the constructor.
>
>
> Modified: python/branches/release25-maint/Python/compile.c
> ==============================================================================
> --- python/branches/release25-maint/Python/compile.c    (original)
> +++ python/branches/release25-maint/Python/compile.c    Mon Feb  4 23:34:57 2008
> @@ -1298,11 +1298,16 @@
>         return b->b_iused++;
>  }
>
> -/* Set the i_lineno member of the instruction at offse off if the
> -   line number for the current expression/statement (?) has not
> +/* Set the i_lineno member of the instruction at offset off if the
> +   line number for the current expression/statement has not
>     already been set.  If it has been set, the call has no effect.
>
> -   Every time a new node is b
> +   The line number is reset in the following cases:
> +   - when entering a new scope
> +   - on each statement
> +   - on each expression that start a new line
> +   - before the "except" clause
> +   - before the "for" and "while" expressions
>     */
>
>  static void
> @@ -2234,9 +2239,8 @@
>         VISIT(c, expr, s->v.For.iter);
>         ADDOP(c, GET_ITER);
>         compiler_use_next_block(c, start);
> -       /* XXX(nnorwitz): is there a better way to handle this?
> -          for loops are special, we want to be able to trace them
> -          each time around, so we need to set an extra line number. */
> +       /* for expressions must be traced on each iteration,
> +          so we need to set an extra line number. */
>         c->u->u_lineno_set = false;
>         ADDOP_JREL(c, FOR_ITER, cleanup);
>         VISIT(c, expr, s->v.For.target);
> @@ -2283,6 +2287,9 @@
>         if (!compiler_push_fblock(c, LOOP, loop))
>                 return 0;
>         if (constant == -1) {
> +               /* while expressions must be traced on each iteration,
> +                  so we need to set an extra line number. */
> +               c->u->u_lineno_set = false;
>                 VISIT(c, expr, s->v.While.test);
>                 ADDOP_JREL(c, JUMP_IF_FALSE, anchor);
>                 ADDOP(c, POP_TOP);
> @@ -2464,8 +2471,8 @@
>                                                 s->v.TryExcept.handlers, i);
>                 if (!handler->type && i < n-1)
>                     return compiler_error(c, "default 'except:' must be last");
> -        c->u->u_lineno_set = false;
> -        c->u->u_lineno = handler->lineno;
> +               c->u->u_lineno_set = false;
> +               c->u->u_lineno = handler->lineno;
>                 except = compiler_new_block(c);
>                 if (except == NULL)
>                         return 0;
> @@ -4184,12 +4191,6 @@
>         assert(d_bytecode >= 0);
>         assert(d_lineno >= 0);
>
> -       /* XXX(nnorwitz): is there a better way to handle this?
> -          for loops are special, we want to be able to trace them
> -          each time around, so we need to set an extra line number. */
> -       if (d_lineno == 0 && i->i_opcode != FOR_ITER)
> -               return 1;
> -
>         if (d_bytecode > 255) {
>                 int j, nbytes, ncodes = d_bytecode / 255;
>                 nbytes = a->a_lnotab_off + 2 * ncodes;
> _______________________________________________
> Python-checkins mailing list
> Python-checkins at python.org
> http://mail.python.org/mailman/listinfo/python-checkins
>


More information about the Python-checkins mailing list