mirror of https://github.com/KLayout/klayout.git
WIP: refinement of Python and Ruby support for keyword arguments.
This commit is contained in:
parent
8f9b904d87
commit
940ef5319a
|
|
@ -195,7 +195,7 @@ type_to_s (const gsi::ArgType &a, bool for_return)
|
|||
s += "[]";
|
||||
break;
|
||||
case gsi::T_map:
|
||||
s += "map<";
|
||||
s += "map<";
|
||||
if (a.inner_k ()) {
|
||||
s += type_to_s (*a.inner_k (), false);
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ type_to_s (const gsi::ArgType &a, bool for_return)
|
|||
if (a.inner ()) {
|
||||
s += type_to_s (*a.inner (), false);
|
||||
}
|
||||
s += ">";
|
||||
s += ">";
|
||||
break;
|
||||
}
|
||||
if (a.is_cptr () || a.is_ptr ()) {
|
||||
|
|
|
|||
|
|
@ -708,7 +708,7 @@ push_args (gsi::SerialArgs &arglist, const gsi::MethodBase *meth, PyObject *args
|
|||
tl::Variant def_value = a->spec ()->default_value ();
|
||||
gsi::push_arg (arglist, *a, def_value, &heap);
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string ("No argument provided (positional or keyword) and no default value available"));
|
||||
throw tl::Exception (tl::to_string (tr ("No argument provided (positional or keyword) and no default value available")));
|
||||
}
|
||||
} else {
|
||||
if (iarg >= argc) {
|
||||
|
|
@ -809,6 +809,10 @@ method_adaptor (int mid, PyObject *self, PyObject *args, PyObject *kwargs)
|
|||
// handle special methods
|
||||
if (meth->smt () != gsi::MethodBase::None) {
|
||||
|
||||
if (kwargs != NULL && PyDict_Size (kwargs) > 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Keyword arguments not permitted")));
|
||||
}
|
||||
|
||||
ret = special_method_impl (meth->smt (), self, args);
|
||||
|
||||
} else {
|
||||
|
|
@ -936,6 +940,10 @@ method_init_adaptor (int mid, PyObject *self, PyObject *args, PyObject *kwargs)
|
|||
|
||||
} else {
|
||||
|
||||
if (kwargs != NULL && PyDict_Size (kwargs) > 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Keyword arguments not permitted")));
|
||||
}
|
||||
|
||||
// No action required - the object is default-created later once it is really required.
|
||||
if (! PyArg_ParseTuple (args, "")) {
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -176,9 +176,9 @@ static VALUE
|
|||
get_kwarg (const gsi::ArgType &atype, VALUE kwargs)
|
||||
{
|
||||
if (kwargs != Qnil) {
|
||||
return rb_hash_lookup2 (kwargs, rb_id2sym (rb_intern (atype.spec ()->name ().c_str ())), Qnil);
|
||||
return rb_hash_lookup2 (kwargs, rb_id2sym (rb_intern (atype.spec ()->name ().c_str ())), Qundef);
|
||||
} else {
|
||||
return Qnil;
|
||||
return Qundef;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -477,7 +477,7 @@ private:
|
|||
int i = 0;
|
||||
for (gsi::MethodBase::argument_iterator a = (*m)->begin_arguments (); is_valid && a != (*m)->end_arguments (); ++a, ++i) {
|
||||
VALUE arg = i >= argc ? get_kwarg (*a, kwargs) : argv[i];
|
||||
if (arg == Qnil) {
|
||||
if (arg == Qundef) {
|
||||
is_valid = a->spec ()->has_default ();
|
||||
} else if (test_arg (*a, arg, false /*strict*/)) {
|
||||
++sc;
|
||||
|
|
@ -1060,7 +1060,7 @@ push_args (gsi::SerialArgs &arglist, const gsi::MethodBase *meth, VALUE *argv, i
|
|||
for (gsi::MethodBase::argument_iterator a = meth->begin_arguments (); a != meth->end_arguments (); ++a, ++iarg) {
|
||||
|
||||
VALUE arg = iarg >= argc ? get_kwarg (*a, kwargs) : argv[iarg];
|
||||
if (arg == Qnil) {
|
||||
if (arg == Qundef) {
|
||||
if (a->spec ()->has_default ()) {
|
||||
if (kwargs_taken == nkwargs) {
|
||||
// leave it to the consumer to establish the default values (that is faster)
|
||||
|
|
@ -1069,7 +1069,7 @@ push_args (gsi::SerialArgs &arglist, const gsi::MethodBase *meth, VALUE *argv, i
|
|||
tl::Variant def_value = a->spec ()->default_value ();
|
||||
gsi::push_arg (arglist, *a, def_value, &heap);
|
||||
} else {
|
||||
throw tl::Exception (tl::to_string ("No argument provided (positional or keyword) and no default value available"));
|
||||
throw tl::Exception (tl::to_string (tr ("No argument provided (positional or keyword) and no default value available")));
|
||||
}
|
||||
} else {
|
||||
if (iarg >= argc) {
|
||||
|
|
@ -1195,10 +1195,18 @@ method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor)
|
|||
|
||||
} else if (meth->smt () != gsi::MethodBase::None) {
|
||||
|
||||
if (kwargs != Qnil && rb_hash_size_num (kwargs) > 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Keyword arguments not permitted")));
|
||||
}
|
||||
|
||||
ret = special_method_impl (meth, argc, argv, self, ctor);
|
||||
|
||||
} else if (meth->is_signal ()) {
|
||||
|
||||
if (kwargs != Qnil && rb_hash_size_num (kwargs) > 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Keyword arguments not permitted on events")));
|
||||
}
|
||||
|
||||
if (p) {
|
||||
|
||||
static ID id_set = rb_intern ("set");
|
||||
|
|
@ -1245,6 +1253,10 @@ method_adaptor (int mid, int argc, VALUE *argv, VALUE self, bool ctor)
|
|||
|
||||
// calling an iterator method without block -> deliver an enumerator using "to_enum"
|
||||
|
||||
if (kwargs != Qnil && rb_hash_size_num (kwargs) > 0) {
|
||||
throw tl::Exception (tl::to_string (tr ("Keyword arguments not permitted on enumerators")));
|
||||
}
|
||||
|
||||
static ID id_to_enum = rb_intern ("to_enum");
|
||||
|
||||
VALUE method_sym = ID2SYM (rb_intern (meth->primary_name ().c_str ()));
|
||||
|
|
|
|||
|
|
@ -172,6 +172,14 @@ class KWArgsTest(unittest.TestCase):
|
|||
except Exception as ex:
|
||||
self.assertEqual(str(ex), "Value cannot be converted to a floating-point value for argument #2 ('dbu') in CplxTrans.to_s")
|
||||
|
||||
try:
|
||||
t = pya.CplxTrans(1.5, 2.5)
|
||||
tt = pya.CplxTrans()
|
||||
tt.assign(other = t)
|
||||
self.assertEqual(True, False)
|
||||
except Exception as ex:
|
||||
self.assertEqual(str(ex), "Keyword arguments not permitted in CplxTrans.assign")
|
||||
|
||||
try:
|
||||
t = pya.CplxTrans("17")
|
||||
self.assertEqual(True, False)
|
||||
|
|
|
|||
|
|
@ -180,6 +180,15 @@ class KWArgs_TestClass < TestBase
|
|||
assert_equal(ex.to_s, "TypeError: no implicit conversion to float from string for argument #2 ('dbu') in CplxTrans::to_s")
|
||||
end
|
||||
|
||||
begin
|
||||
t = RBA::CplxTrans::new(1.5, 2.5)
|
||||
tt = RBA::CplxTrans::new
|
||||
tt.assign(other: t)
|
||||
assert_equal(true, false)
|
||||
rescue => ex
|
||||
assert_equal(ex.to_s, "Keyword arguments not permitted in CplxTrans::assign")
|
||||
end
|
||||
|
||||
begin
|
||||
t = RBA::CplxTrans::new("17")
|
||||
assert_equal(true, false)
|
||||
|
|
|
|||
|
|
@ -301,10 +301,10 @@ class Tl_TestClass < TestBase
|
|||
assert_equal(my_recipe.name, "rba_test_recipe")
|
||||
assert_equal(my_recipe.description, "description")
|
||||
|
||||
g = my_recipe.generator("A" => 6, "B" => 7.0)
|
||||
g = my_recipe.generator({ "A" => 6, "B" => 7.0 })
|
||||
assert_equal(g, "rba_test_recipe: A=#6,B=##7")
|
||||
assert_equal("%g" % RBA::Recipe::make(g), "42")
|
||||
assert_equal("%g" % RBA::Recipe::make(g, "C" => 1.5).to_s, "63")
|
||||
assert_equal("%g" % RBA::Recipe::make(g, { "C" => 1.5 }).to_s, "63")
|
||||
|
||||
my_recipe._destroy
|
||||
my_recipe = nil
|
||||
|
|
|
|||
Loading…
Reference in New Issue