ANN: Yats 0.1

Alex Martelli aleaxit at yahoo.com
Mon May 21 04:15:53 EDT 2001


"Brett Haydon" <bbhaydon at bigpond.com> wrote in message
news:df2ee32b.0105202010.1669d188 at posting.google.com...
> "Alex Martelli" <aleaxit at yahoo.com> wrote in message
news:<9e9f1u01a2l at enews1.newsguy.com>...
> > YAPTU serves the purpose of offering a general text-templating
> > (aka text-embedded Python) in a few dozen lines...:-).  [OK, so it
> > IS _slightly_ kludgey, but, hey, it IS general and tiny...:-)].
>
> Hmm, if I'd seen yours I probably wouldn't have bothered to post
> mine up.. but actually they do seem a bit different.

Good thing you *didn't* see Yaptu earlier, then, because "the more
the better":-).  Yep, there ARE differences!  YATS and YAPTU both
have worth, and studying and comparing/contrasting them might be
an interesting exercise, if nothing else:-).


> I looked at evaluating expressions and executing arbitrary code,
> but outside of the local namespace ie in the calling scripts globals().
> So a tag {!sometag="Something") would return a string (or not) from
> function sometag("Something") in the globals() of the script that is
> using yats.
>
> The idea being that some tags in a given page are likely to be repeated
> in every page and it seems silly to have to specifically code for them
> each time..
>
> But, for that to happen I need to pass gobals() each time I instantiate
> a TemplateDocument class ie
page=TemplateDocument("somedoc.html',globals())

Exactly.  This is the tack I took in YAPTU -- minimize black magick,
let the caller EXPLICITLY pass the dictionaries in which the execution
and evaluation of Python code "embedded in text" is to occur.


> Does anyone know a way that a class can receive the calling functions
> globals() or locals() without it being explicitly passed in each instance.

Yep -- as far as black-magic goes, these are fairly well-known spells:-).
To the point that, in Python 2.1, a built-in function that helps with this
even made it all the way to the sys module, albeit suitably hedged with
leading-underscore name and warnings...:
"""
_getframe([depth])
Return a frame object from the call stack. If optional integer depth
is given, return the frame object that many calls below the top of the
stack. If that is deeper than the call stack, ValueError is raised. The
default for depth is zero, returning the frame at the top of the call
stack.
This function should be used for internal and specialized purposes only.
"""

You can get a similar effect in earlier Python versions by raising and
catching an exception and walking the resulting traceback yourself:

def caller_frame():
    try: raise "boo"
    except: return sys.exc_traceback.tb_frame.f_back.f_back

In either case, you end up with a stackframe object, which among its
attributes has f_globals and f_locals.  If you treat those as read-only,
I think the magic involved can fairly be described as "darkish-gray"
rather than black -- it wouldn't be TOO terrible to use it in production
code, although the need for such use should IMHO be carefully vetted.

Anyway, a usage example might be:

>>> import sys
>>> def f(a, b=23):
...     c=45
...     g()
...
>>> def g():
...     x=sys._getframe(1)
...     print x.f_locals
...
>>> f(99)
{'b': 23, 'c': 45, 'a': 99}
>>>

or, similarly,

>>> def g():
...     x=caller_frame()
...     print x.f_locals

Et voila -- you have (read-only, pls:-) access to the locals of
the function calling you.  globals work similarly, of course.


> Or maybe there's another way of looking at it

"Explicit is better than implicit" and "don't do black magick
behind my back please" might be these "other ways":-).  Python
gives you A LOT of access to the kind of things that most other
languages keep carefully hidden behind smoke and mirrors, and
this empowers you, as a designer and programmer, to decide how
"normal" or "magical" you want your libraries/modules/programs
to be.  However, my personal opinion, for what it's worth, is
that such tools are mostly to be used in developing frameworks
and tools for debugging, experimentation, etc -- production code
being (again IMHO) cleaner and more readable and maintainable
if tricks are systematically eschewed in favour of simplicity,
explicitness, straightforwardhood (yep, I know the latter is not
a word:-).  It's *SO* much fun to play with the black-magic
(introspection/reflection/metaprogramming) possibilities, that
being carried away with it is a risk -- it's exactly to counter
this risk (in myself first of all:-) that I keep harping on it:-).


Alex






More information about the Python-list mailing list