[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