with_meta and stack frame issues

Issue #83 new
created an issue

[I also reported this issue to the python-future people, here: https://github.com/PythonCharmers/python-future/issues/75]

In Morepath, I use a library Venusian within a metaclass to attach some information. Venusian goes up the frames to find out in which context the attachment takes place (module, class).

Introducing the metaclass in Morepath broke its Python 3 compatibility. So I tried to use future.utils.with_meta. I couldn't make it work -- the depth of the stack frame had changed. I adjusted the Venusian call to use an increased depth, but from my limited debugging, the depth of the stack frame seems to vary depending on whether a class (with a metaclass) is defined in a function or in a module-level context.

I discovered future contains a copy of six. So I tried using future.utils.six's with_meta and all my tests passed without a problem in Python 2, Python 3 and PyPy. I didn't need to adjust the depth either.

To make matters more exciting, I switched to six proper, 1.7.3, which is presumably a more recent version than the copy in python-future, and all my tests broke again in a similar way to python-future's...

I thought I'd better report this problem.

Meanwhile I think it's best to take old-six's version and copy it into Morepath. I guess it isn't perfect, but it seems to work for my purposes.

It would be nice if at the very least with_meta's stack frame behavior could be made consistent all the way through. Preferably level 1 of depth like plain Python, but if it's to be 2, I can adjust for that, as long as it's the same in all circumstances and versions of Python.

I'd also like to know why the old version in six needed to be adjusted -- presumably it fixes some issues with metaclasses, and since the old version does the job for my metaclass, I wonder what's wrong with it and if it's going to bite me.

Comments (4)

  1. faassen reporter

    The old version is very simple:

    def with_metaclass(meta, *bases):
        """Create a base class with a metaclass."""
        return meta("NewBase", bases, {})
  2. faassen reporter

    Thanks, that explains a bit more!

    I'd like to use the new implementation if possible, but the stack frame issues block me at present.

    Looking at metaclass code is a good way to make your head explode, but the obvious bit that could make the stack frames vary is the if clause. One way to make progress is to write a few tests that demonstrate the stack frame varies depending on the metaclass depth, I'll look into this.

  3. Log in to comment