Diffs to the cvs from before couple of days: David Abrahams wrote:
Nikolay Mladenov ?nickm@sitius.com? writes:
? 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.
Hmm, it seems likely that I will. 1.29.0 is two releases old and we have made a lot of changes since then. Is there any chance you can give me a patch against the current CVS state?
-- Dave Abrahams Boost Consulting www.boost-consulting.com
Index: args.hpp =================================================================== RCS file: /d/Downloads/boost/boost/boost/python/args.hpp,v retrieving revision 1.14 diff -c -r1.14 args.hpp *** args.hpp 31 May 2003 14:53:01 -0000 1.14 --- args.hpp 28 Jul 2003 21:47:00 -0000 *************** *** 44,51 **** --- 44,62 ---- } keyword elements[nkeywords]; + 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; }; + + + # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template<typename T> struct is_keywords *************** *** 95,100 **** --- 106,132 ---- BOOST_PYTHON_MPL_LAMBDA_SUPPORT(1,is_reference_to_keywords,(T)) }; # endif + } + + 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)); + } } # define BOOST_PYTHON_ASSIGN_NAME(z, n, _) result.elements[n].name = name##n; Index: args_fwd.hpp =================================================================== RCS file: /d/Downloads/boost/boost/boost/python/args_fwd.hpp,v retrieving revision 1.3 diff -c -r1.3 args_fwd.hpp *** args_fwd.hpp 31 May 2003 14:53:01 -0000 1.3 --- args_fwd.hpp 28 Jul 2003 21:47:01 -0000 *************** *** 21,26 **** --- 21,27 ---- { char const* name; handle<> default_value; + keyword(char const* n=0):name(n){} }; template <std::size_t nkeywords = 0> struct keywords; Index: function.hpp =================================================================== RCS file: /d/Downloads/boost/boost/boost/python/object/function.hpp,v retrieving revision 1.18 diff -c -r1.18 function.hpp *** function.hpp 23 Jul 2003 13:08:59 -0000 1.18 --- function.hpp 28 Jul 2003 21:48:13 -0000 *************** *** 51,56 **** --- 51,57 ---- object m_namespace; object m_doc; object m_arg_names; + unsigned m_nkeyword_values; }; // Index: function.cpp =================================================================== RCS file: /d/Downloads/boost/boost/libs/python/src/object/function.cpp,v retrieving revision 1.33 diff -b -c -r1.33 function.cpp *** function.cpp 23 Jul 2003 17:04:05 -0000 1.33 --- function.cpp 31 Jul 2003 17:07:21 -0000 *************** *** 47,52 **** --- 47,53 ---- , unsigned num_keywords ) : m_fn(implementation) + , m_nkeyword_values(0) { if (names_and_defaults != 0) { *************** *** 66,78 **** for (unsigned i = 0; i < num_keywords; ++i) { PyTuple_SET_ITEM( ! m_arg_names.ptr() ! , i + keyword_offset , expect_non_null( PyString_FromString(const_cast<char*>(names_and_defaults[i].name)) ) ); } } --- 67,101 ---- for (unsigned i = 0; i < num_keywords; ++i) { + object tpl (handle<>( + PyTuple_New(names_and_defaults[i].default_value ? 2 : 1) + )); + PyTuple_SET_ITEM( ! tpl.ptr() ! , 0 , expect_non_null( PyString_FromString(const_cast<char*>(names_and_defaults[i].name)) ) ); + + 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()) + ); } } *************** *** 101,114 **** do { // Check for a plausible number of arguments ! if (total_args >= f->m_fn.min_arity() ! && total_args <= f->m_fn.max_arity()) { // This will be the args that actually get passed handle<> args2(allow_null(borrowed(args))); ! if (nkeywords > 0) // Keyword arguments were supplied ! { if (f->m_arg_names.ptr() == Py_None) // this overload doesn't accept keywords { args2 = handle<>(); // signal failure --- 124,140 ---- do { // Check for a plausible number of arguments ! unsigned min_arity = f->m_fn.min_arity(); ! unsigned max_arity = f->m_fn.max_arity(); ! ! if (total_args + f->m_nkeyword_values >= min_arity ! && total_args <= max_arity) { // This will be the args that actually get passed handle<> args2(allow_null(borrowed(args))); ! if (nkeywords > 0 || total_args < min_arity) // Keyword arguments were supplied ! { // or default keyword values are needed if (f->m_arg_names.ptr() == Py_None) // this overload doesn't accept keywords { args2 = handle<>(); // signal failure *************** *** 131,148 **** } else { ! // build a new arg tuple ! args2 = handle<>(PyTuple_New(total_args)); // Fill in the positional arguments for (std::size_t i = 0; i < nargs; ++i) PyTuple_SET_ITEM(args2.get(), i, incref(PyTuple_GET_ITEM(args, i))); // Grab remaining arguments by name from the keyword dictionary ! for (std::size_t j = nargs; j < total_args; ++j) { ! PyObject* value = PyDict_GetItem( ! keywords, PyTuple_GET_ITEM(f->m_arg_names.ptr(), j)); if (!value) { --- 157,185 ---- } else { ! // build a new arg tuple, will adjust its size later ! args2 = handle<>(PyTuple_New(max_arity)); // Fill in the positional arguments for (std::size_t i = 0; i < nargs; ++i) PyTuple_SET_ITEM(args2.get(), i, incref(PyTuple_GET_ITEM(args, i))); // Grab remaining arguments by name from the keyword dictionary ! std::size_t j = nargs; ! std::size_t k = nargs; ! std::size_t size = PyTuple_GET_SIZE(f->m_arg_names.ptr()); ! ! for (; j < max_arity && j < size ; ++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); if (!value) { *************** *** 150,156 **** args2 = handle<>(); break; } ! PyTuple_SET_ITEM(args2.get(), j, incref(value)); } } } --- 187,217 ---- args2 = handle<>(); break; } ! }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<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')
# lets see how badly we've broken the 'regular' functions
f = Bar() f.a(), f.b(), f.n() (0, 0.0, '') f = Bar(1) f.a(), f.b(), f.n() (1, 0.0, '') f = Bar(1,1.0) f.a(), f.b(), f.n() (1, 1.0, '') f = Bar(1,1.0,"1") f.a(), f.b(), f.n() (1, 1.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') '''
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])