Support py3k kwonly args #7

Merged
merged 2 commits into from Feb 11, 2014

Projects

None yet

2 participants

@eevee

They were being correctly parsed already, but a template like this:

<%def name="asdf(*qwert, zxcv='hi')">${zxcv}</%def>

would generate code like this:

def render_asdf(context,*qwert):
    __M_caller = context.caller_stack._push_frame()
    try:
        zxcv = context.get('zxcv', UNDEFINED)
    ...

which would then either TypeError when called with the required keyword argument, or (if there were also a **kwargs) have the argument overwritten by UNDEFINED right out of the gate.

Should work now. Added a few tests. Everything passes on Python 2.7, Python 3.3, and PyPy 2.2.1 (except for two tests that fail PyPy in Beaker somewhere, so not a Mako problem).

Inspired by... mitsuhiko, or python-future, or someone?, I added a compat.py2k, so code can be written as though Python 3 were the default and Python 2 were the special case.

I also made a best effort at the _ast-less code path; four tests fail, but all four of them are problems with how Pygments decided to color the syntax, so I assume that's just an inherent issue with the compiler module. (Two of them are marked as requiring Python 2.5+, so will never run in practice anyway.)

eevee added some commits Feb 11, 2014
@eevee eevee Support Python 3's keyword-only arguments.
Previously, they would parse correctly in Python 3, but any keyword-only
arguments would be quietly lost, and the user would either get
`TypeError: foo() got an unexpected keyword argument...` or the
confusing behavior of having the keyword argument overwritten with
whatever's in the context with the same name.
836e5f9
@eevee eevee Make a best effort at pre-2.5 compatibility. 11a2349
@zzzeek
Owner

that is a motherlode of a pullrequest, bud, i need to take some time to see what im lookin at.

@zzzeek

random guess, x[::-1] means "reversed()". going to try that now. (tries) it does! but i know, why use plain english "reversed" when you can perl it up.... :)

iirc reverse is actually the only way to do this in perl!

but in python 3 reversed always returns an iterator, so .pop won't work. so it'd have to be list(reversed(...)) which is a bit much imo :)

Owner

damn that py3k and its iterators!

@eevee

some brief explanation is perhaps in order:

py2 has args, vararg, kwarg, defaults.

py3 adds kwonlyargs and kw_defaults, for single args that come after *args. the defaults are separate because they don't have to be clustered all at the end; def foo(*, a=1, b, c=3) is totally valid. (it also adds attributes for annotations, but i have no idea how to make those work here.)

so now positional and named args are much more similar: there can be any number of them, some of them might have defaults, and there might be a slurpy one at the end. so i split up the names and defaults and handle them separately

@zzzeek
Owner

did you mark the failing tests as skip? I'm not getting any failures even if i run nose in python 2.4. these tests only fail when pygments is installed?

@eevee

Yeah, two are 2.5+ only and two require Pygments 1.4+. Does Pygments not work on 2.4 any more? I couldn't find a minimum version mentioned anywhere,

@zzzeek
Owner

im pretty unconcerned about py2.4, supporting it is mostly just a practice exercise at this point.

@zzzeek zzzeek merged commit 11a2349 into zzzeek:master Feb 11, 2014
@zzzeek
Owner

woop, thanks a bunch! maybe ill even release 0.9.2 soon.

@eevee

woo thanks :)

@eevee eevee deleted the eevee:support-py3k-kwonly-args branch Aug 2, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment