Browse Source

allow KwArgs after VarArgs, allow passing null for VarArgs and KwArgs (fixes problem when they are optional arguments and become null implicitly

frabbit 11 years ago
parent
commit
a5d8dc6699
4 changed files with 70 additions and 7 deletions
  1. 12 3
      genpy.ml
  2. 1 1
      std/python/KwArgs.hx
  3. 1 3
      std/python/Lib.hx
  4. 56 0
      tests/unit/TestPython.hx

+ 12 - 3
genpy.ml

@@ -1048,17 +1048,21 @@ module Printer = struct
 	let print_args args p =
 	let print_args args p =
 		let had_value = ref false in
 		let had_value = ref false in
 		let had_var_args = ref false in
 		let had_var_args = ref false in
+		let had_kw_args = ref false in
 		let sl = List.map (fun (v,cto) ->
 		let sl = List.map (fun (v,cto) ->
-			if !had_var_args then error "Arguments after KwArgs/VarArgs are not allowed" p;
+			let check_err () = if !had_var_args || !had_kw_args then error "Arguments after KwArgs/VarArgs are not allowed" p in
 			let name = handle_keywords v.v_name in
 			let name = handle_keywords v.v_name in
 			match follow v.v_type with
 			match follow v.v_type with
 				| TAbstract({a_path = ["python"],"KwArgs"},_) ->
 				| TAbstract({a_path = ["python"],"KwArgs"},_) ->
-					had_var_args := true;
+					if !had_kw_args then error "Arguments after KwArgs are not allowed" p;
+					had_kw_args := true;
 					"**" ^ name
 					"**" ^ name
 				| TAbstract({a_path = ["python"],"VarArgs"},_) ->
 				| TAbstract({a_path = ["python"],"VarArgs"},_) ->
+					check_err ();
 					had_var_args := true;
 					had_var_args := true;
 					"*" ^ name
 					"*" ^ name
 				| _ ->
 				| _ ->
+					check_err ();
 					name ^ match cto with
 					name ^ match cto with
 						| None when !had_value -> " = None"
 						| None when !had_value -> " = None"
 						| None -> ""
 						| None -> ""
@@ -1511,6 +1515,11 @@ module Printer = struct
 
 
 	and print_call_args pctx e1 el =
 	and print_call_args pctx e1 el =
 		let print_arg pctx i x =
 		let print_arg pctx i x =
+			let e = match x.eexpr, follow x.etype with
+				| TConst TNull, TAbstract({a_path = ["python"],"KwArgs"},_) -> "{}"
+				| TConst TNull, TAbstract({a_path = ["python"],"VarArgs"},_) -> "[]"
+				| _ -> (print_expr pctx x)
+			in
 			let prefix = match e1.eexpr, follow x.etype with
 			let prefix = match e1.eexpr, follow x.etype with
 				(* the should not apply for the instance methods of the abstract itself *)
 				(* the should not apply for the instance methods of the abstract itself *)
 				| TField(_, FStatic({cl_path = ["python"; "_KwArgs"],"KwArgs_Impl_"},f)), _ when i == 0 && Meta.has Meta.Impl f.cf_meta -> ""
 				| TField(_, FStatic({cl_path = ["python"; "_KwArgs"],"KwArgs_Impl_"},f)), _ when i == 0 && Meta.has Meta.Impl f.cf_meta -> ""
@@ -1519,7 +1528,7 @@ module Printer = struct
 				| _, TAbstract({a_path = ["python"],"VarArgs"},_) -> "*"
 				| _, TAbstract({a_path = ["python"],"VarArgs"},_) -> "*"
 				| _, _ -> ""
 				| _, _ -> ""
 			in
 			in
-			prefix ^ (print_expr pctx x)
+			prefix ^ e
 		in
 		in
 		String.concat "," (ExtList.List.mapi (print_arg pctx) el)
 		String.concat "," (ExtList.List.mapi (print_arg pctx) el)
 
 

+ 1 - 1
std/python/KwArgs.hx

@@ -7,7 +7,7 @@ abstract KwArgs (Dict<String, Dynamic>)
 {
 {
 	inline function new (d:Dict<String, Dynamic>) this = d;
 	inline function new (d:Dict<String, Dynamic>) this = d;
 
 
-	@:to inline function toDict ():Dict<String, Dynamic>
+	@:to public inline function toDict ():Dict<String, Dynamic>
 	{
 	{
 		return this;
 		return this;
 	}
 	}

+ 1 - 3
std/python/Lib.hx

@@ -26,12 +26,10 @@ class Lib {
 	public static function dictToAnon (v:Dict<String, Dynamic>):Dynamic
 	public static function dictToAnon (v:Dict<String, Dynamic>):Dynamic
 	{
 	{
 		return new AnonObject(v.copy());
 		return new AnonObject(v.copy());
-
-		//return o;
 	}
 	}
 
 
 
 
-	public static function anonToDict (o:{}):Dynamic
+	public static function anonToDict (o:{}):Dict<String, Dynamic>
 	{
 	{
 		return if (HxBuiltin.isinstance(o, AnonObject))
 		return if (HxBuiltin.isinstance(o, AnonObject))
 		{
 		{

+ 56 - 0
tests/unit/TestPython.hx

@@ -241,7 +241,61 @@ class TestPython extends Test {
 		eq(3, res);
 		eq(3, res);
 	}
 	}
 
 
+	function testKwArgsAfterVarArgs () {
+		function test (va:VarArgs, kw:KwArgs) {
+			var a = va.toArray();
+
+			eq(1,a[0]);
+			eq(2,a[1]);
+			eq(1,kw.get("a", null));
+		}
+		var a = python.Lib.anonToDict({ "a" : 1});
+		var x = [1,2];
+		test(x,a);
+	}
+
+	function testOptionalVarArgs () {
+		function test (?va:VarArgs, ?kw:KwArgs) {
+			var a = va.toArray();
+
+			eq(0,a.length);
+		}
+		test();
+	}
+
+	function testOptionalKwArgs () {
+		function test (?kw:KwArgs) eq(0,kw.toDict().length());
+		test();
+	}
+
+	function testOptionalKwArgsAfterOptionalVarArgs () {
+		function test (?va:VarArgs, ?kw:KwArgs) {
+			var a = va.toArray();
+
+			eq(1,a[0]);
+			eq(2,a[1]);
+
+			eq(0, kw.toDict().length());
+		}
+		var x = [1,2];
+		test(x);
+
+
+
+		function test (?va:VarArgs, ?kw:KwArgs) {
+			var a = va.toArray();
+			eq(0,a.length);
+			eq(1, kw.get("a",null));
+		}
+
+		var a = python.Lib.anonToDict({ "a" : 1});
+
+		test(a);
+	}
+
 	function testKwArgs () {
 	function testKwArgs () {
+
+
 		function x (args:KwArgs) {
 		function x (args:KwArgs) {
 			var a = args.get("a", 0);
 			var a = args.get("a", 0);
 			var b = args.get("b", 0);
 			var b = args.get("b", 0);
@@ -336,6 +390,8 @@ class TestPython extends Test {
 		eq(t.length, 2);
 		eq(t.length, 2);
 	}
 	}
 
 
+
+
 	function testExtern()
 	function testExtern()
 	{
 	{
 		eq(new ExternClass().f(1), 2);
 		eq(new ExternClass().f(1), 2);