[C++-sig] Re: args patch
Nikolay Mladenov
nickm at sitius.com
Thu Jul 31 19:17:41 CEST 2003
Diffs to the cvs from before couple of days:
David Abrahams wrote:
>
> Nikolay Mladenov ?nickm at 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
-------------- next part --------------
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;
-------------- next part --------------
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;
-------------- next part --------------
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;
};
//
-------------- next part --------------
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;
! }
}
}
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: keywords.cpp
Type: application/x-unknown-content-type-cppfile
Size: 2489 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20030731/8d4e2bbb/attachment.bin>
-------------- next part --------------
'''
>>> 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])
More information about the Cplusplus-sig
mailing list