Dave, I am posting the diffs from 1.29.0 plus the test and doc files. Sorry for the delay. I hope you won't have problems applying the diffs. Nikolay 44a45,52
keywords<size+1> operator , (const keywords<1> &k) const { python::detail::keywords<size+1> res; std::copy(elements, elements+size, res.elements); res.elements[size] = k.elements[0]; return res; } keywords<size+1> operator , (const char *name) const;
46a55,57
97a109,129
struct arg : detail::keywords<1> { template <class T> arg &operator = (T const &value) { elements[0].default_value = handle<>(python::borrowed(object(value).ptr())); return *this; } explicit arg (char const *name){elements[0].name = name;} operator detail::keyword const &()const {return elements[0];} };
namespace detail { template <std::size_t nkeywords> inline keywords< keywords<nkeywords>::size+1 > keywords<nkeywords>::operator , (const char *name) const { return this->operator , (arg(name)); } }
21a22
keyword(char const* n=0):name(n){}
57a58
unsigned m_nkeyword_values;
35a36
, m_nkeyword_values(0)
42d42 < 48a49,52
object tpl (handle<>( PyTuple_New(names_and_defaults[i].default_value ? 2 : 1) ));
50,51c54,55 < m_arg_names.ptr() < , i + keyword_offset ---
tpl.ptr() , 0
55a60,77
if(names_and_defaults[i].default_value) { PyTuple_SET_ITEM( tpl.ptr() , 1 , incref(names_and_defaults[i].default_value.get()) );
++m_nkeyword_values; }
PyTuple_SET_ITEM( m_arg_names.ptr() , i + keyword_offset , incref(tpl.ptr()) );
82c104 < if (total_args >= f->m_min_arity && total_args <= f->m_max_arity) ---
if (total_args + f->m_nkeyword_values >= f->m_min_arity && total_args <= f->m_max_arity)
85c107 < if (nkeywords > 0) ---
if (nkeywords > 0 || total_args < f->m_min_arity)
94,95c116,117 < // build a new arg tuple < args2 = handle<>(PyTuple_New(total_args)); ---
// build a new arg tuple, will adjust its size later args2 = handle<>(PyTuple_New(f->m_max_arity));
102c124,128 < for (std::size_t j = nargs; j < total_args; ++j) ---
std::size_t j = nargs; std::size_t k = nargs; std::size_t size = PyTuple_GET_SIZE(f->m_arg_names.ptr());
for (; j < f->m_max_arity && j < size ; ++j)
104,105c130,138 < PyObject* value = PyDict_GetItem( < keywords, PyTuple_GET_ITEM(f->m_arg_names.ptr(), j)); ---
PyObject* kwd = PyTuple_GET_ITEM(f->m_arg_names.ptr(), j);
PyObject* value = nkeywords ? PyDict_GetItem( keywords, PyTuple_GET_ITEM(kwd, 0)) : 0;
if (!value) { if (PyTuple_GET_SIZE(kwd) > 1) value = PyTuple_GET_ITEM(kwd, 1);
113c146,170 < PyTuple_SET_ITEM(args2.get(), j, incref(value)); ---
}else ++k;
PyTuple_SET_ITEM(args2.get(), j, incref(value) ); }
if (args2.get()) { //check if we proccessed all the arguments if(k < total_args) args2 = handle<>();
//adjust the parameter tuple size if(j<f->m_max_arity) { handle<> args3( PyTuple_New(j) );
for (size_t l = 0; l != j; ++ l) { PyTuple_SET_ITEM(args3.get(), l, PyTuple_GET_ITEM(args3.get(), l) ); PyTuple_SET_ITEM(args2.get(), l, 0); } args2 = args3; }
'''
from keywords import * f = Foo() f.a(), f.b(), f.n() (0, 0.0, '') f = Foo(1) f.a(), f.b(), f.n() (1, 0.0, '') f = Foo(1,1.0) f.a(), f.b(), f.n() (1, 1.0, '') f = Foo(1,1.0,"1") f.a(), f.b(), f.n() (1, 1.0, '1') f = Foo(a=1) f.a(), f.b(), f.n() (1, 0.0, '') f = Foo(b=1) f.a(), f.b(), f.n() (0, 1.0, '') f = Foo(n="1") f.a(), f.b(), f.n() (0, 0.0, '1') f = Foo(1,n="1") f.a(), f.b(), f.n() (1, 0.0, '1') f.set() f.a(), f.b(), f.n() (0, 0.0, '') f.set(1) f.a(), f.b(), f.n() (1, 0.0, '') f.set(1,1.0) f.a(), f.b(), f.n() (1, 1.0, '') f.set(1,1.0,"1") f.a(), f.b(), f.n() (1, 1.0, '1') f.set(a=1) f.a(), f.b(), f.n() (1, 0.0, '') f.set(b=1) f.a(), f.b(), f.n() (0, 1.0, '') f.set(n="1") f.a(), f.b(), f.n() (0, 0.0, '1') f.set(1,n="1") f.a(), f.b(), f.n() (1, 0.0, '1') '''
def run(args = None): import sys import doctest if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) if __name__ == '__main__': print "running..." import sys sys.exit(run()[0])