I'm hoping that this is pretty straight-forward. Here's to hoping.

I'm attempting to build a Java object that can see what Jython function called its method(s). In Jython, as in regular Python, I'd do this through the inspect module:

import inspect

def _code(num):
    return inspect.getouterframes(inspect.currentframe())[num + 2][0].f_code

def caller_name():
    return inspect.getouterframes(inspect.currentframe())[2][0].f_code.co_name

However, I'm not able to use a Jython call in this instance, due to performance constraints (the Google App Engine has a one minute requirement for all servlet calls to return, their "Hard Deadline", and when I built the object in Jython, it easily exceeded this hard deadline. So I built a Java object that relies on the magic metho/function names in Jython to "pretend" to be a Python object.

This all goes toward being able to write fairly clean, Pythonic code for sorting algorithms (for my showsort app), which will serve a couple purposes. First and foremost, actually running the sorts as it does, and second, I want to eventually have the actual code which is running in the sorting routines/algorithms be able to be displayed for the viewer. My trick is I'm storing the sorting algorithms in the Google Apps Engine DataStore (using some JDO trickery). I already have this functionality in place, and it works quite well, the source code for the sorting algorithms is stored in a Text field on the DataStore, and whenever a sort is requested, it loads the routine, compiles it, and then executes the routine. The "array" that the routine runs against is this Java object I've built, which relies on Jython special methods in order to produce a number of statistics during the sort: the number of comparisons that were done on the array's elements, the number of recursive calls done, the amount of memory which has been used by the sorting algorithm, and the number of moves (changes) to the array's elements that have been requested.

So far, this has been a piece of cake. I've built the sorting algorithms relying heavily on Jython generators for "lazy computing" of the sorts, which allows me to capture each and every change that the routine has done, like so:

def sort(arr):
    for i in range(len(arr), 0, -1):
        for j in range(1, i):
            if arr[j - 1] > arr[j]:
                yield arr.swap(j - 1, j)

That is my routine for a Bubble Sort. It should be fairly clear and clean, something even (I hope) non-Python people would be able to easily grasp. My goal is to make each and every routine look as much like pseudo-code as possible, which means I want to minimize the Python-specific syntax as possible. The yield lines in my code show where an update has taken place.

The difficulty I had was when I got to recursive algorithms, like Quicksort:

def sort(arr):
    def quick_sort(arr, left, right):
        l_hold, r_hold, pivot = left, right, arr[left]

        while left < right:
            while arr[right] >= pivot and left < right:
                right -= 1

            if left != right:
                yield arr.change(left, arr[right])
                left += 1

            while arr[left] <= pivot and left < right:
                left += 1

            if left != right:
                yield arr.change(right, arr[left])
                right -= 1

        yield arr.change(left, pivot)

        if l_hold < left:
            yield quick_sort(arr, l_hold, left - 1)

        if r_hold > left:
            yield quick_sort(arr, left + 1, r_hold)

What I built was a routine that when it processes the generator object, it looks for if the next element from the generator is, in fact, another generator object. If so, it identifies this as a recursive call, and recursively calls itself with the new generator object as a parameter:

    def process(self, stepList):
        """
        Processes each generator that is created to build the list of updates
        to send back to the client app.
        """
        recurseChecked = False
       
        log.debug3("Function caller: " + self.arr.getCallerName())
       
        for step in stepList:
            if recurseChecked == False and self.last_func != None and self.last_func == self.arr.getCallerName():
                self.arr.incrRecurses()
            recurseChecked = True
            self.last_func = self.arr.getCallerName()
           
            if type(step) is types.GeneratorType:
                self.process(step)
            else:
                self.updList.append(step)

This worked great, until I built the Heapsort algorithm:

def sort(arr):
    def siftDown(arr, first, last):
        while 2 * first + 1 <= last:
            k = 2 * first + 1
           
            if k < last and arr[k] < arr[k + 1]:
                k += 1
               
            if arr[first] >= arr[k]:
                break
           
            yield arr.swap(first, k)
            first = k

    first, last = 0, len(arr) - 1

    for i in range(int(last / 2), first - 1, -1):
        yield siftDown(arr, i, last)

    for i in range(last, first, -1):
        yield arr.swap(i, first)
        yield siftDown(arr, first, i - 1)

This is the code I'd like to run. However I'm finding it impossible, in this context, to properly identify a recursive call versus a regular function call. Now, I could write the "yield siftDown" lines in Heapsort as:

for upd in yield siftDown(arr, i, last): yield upd

Which fixes the problem of determining what is or isn't recursive. However it makes the code a little more ugly and hard to read, something that defeats one of my original purposes in all of this.

So, I have been trying to get my Java object (the arr object that the sort functions are using) to be able to track the name of the Jython function that called the swap() or change() methods. Then I could, in my process() method/function be able to determine what is or isn't a recursive call by simply comparing the function names between recursive calls to process(). That would make the syntax for both recursive and non-recursive function calls appear to be the same in my sorting algorithm code, and make the system be smart enough to tell the difference.

but I'm stuck at this point. So... any help would be appreciated.

--
"I'm not responcabel fer my computer's spleling errnors" - Xlorep DarkHelm
Website: http://darkhelm.org