Bläddra i källkod

[python] add support for typed KwArgs like KwArgs<{ foo : String}>

frabbit 10 år sedan
förälder
incheckning
db98dbb4f8

+ 12 - 4
std/python/KwArgs.hx

@@ -1,9 +1,8 @@
-
 package python;
 
 import python.lib.Dict;
 
-abstract KwArgs (Dict<String, Dynamic>)
+abstract KwArgs<T:{}> (Dict<String, Dynamic>)
 {
 	inline function new (d:Dict<String, Dynamic>) this = d;
 
@@ -11,13 +10,22 @@ abstract KwArgs (Dict<String, Dynamic>)
 	{
 		return this;
 	}
-	@:from static inline function fromDict (d:Dict<String, Dynamic>):KwArgs
+	@:from static inline function fromDict (d:Dict<String, Dynamic>):KwArgs<Dynamic>
 	{
 		return new KwArgs(d);
 	}
+	@:from static inline function fromT <T:{}>(d:T):KwArgs<T>
+	{
+		return new KwArgs(Lib.anonAsDict(d));
+	}
+
+	public function typed ():T
+	{
+		return Lib.dictAsAnon(toDict());
+	}
 
 	public function get <V>(key:String, def:V):V
 	{
 		return this.get(key, def);
 	}
-}
+}

+ 28 - 4
std/python/Lib.hx

@@ -22,14 +22,18 @@ class Lib {
 		PySys.stdout.flush();
 	}
 
-	public static function dictToAnon (v:Dict<String, Dynamic>):Dynamic
-	{
+	/**
+	 	Returns an anonymous Object which holds the same data as the Dictionary `v`.
+	**/
+	public static function dictToAnon (v:Dict<String, Dynamic>):Dynamic {
 		return new AnonObject(v.copy());
 	}
 
 
-	public static function anonToDict (o:{}):Dict<String, Dynamic>
-	{
+	/**
+	 	Returns a flat copy of the underlying Dictionary of `o`.
+	**/
+	public static function anonToDict (o:{}):Dict<String, Dynamic> {
 		return if (python.lib.Builtin.isinstance(o, AnonObject))
 		{
 			(Syntax.field(o, "__dict__"):Dict<String,Dynamic>).copy();
@@ -38,6 +42,26 @@ class Lib {
 
 	}
 
+	/**
+	 	Returns the underlying Dictionary of the anonymous object `o`.
+	 	Modifications to this dictionary are reflected in the anonymous Object too.
+	**/
+	public static function anonAsDict (o:{}):Dict<String, Dynamic> {
+		return if (python.lib.Builtin.isinstance(o, AnonObject))
+		{
+			(Syntax.field(o, "__dict__"):Dict<String,Dynamic>);
+		}
+		else null;
+	}
+
+	/**
+	 	Returns the Dictionary `d` as an anonymous Object.
+	 	Modifications to the object are reflected in the Dictionary too.
+	**/
+	public static function dictAsAnon (d:Dict<String, Dynamic>):Dynamic {
+		return new AnonObject(d);
+	}
+
 	public static function toPythonIterable <T>(it:Iterable<T>):python.NativeIterable<T> {
 		return {
 			__iter__ : function () {

+ 1 - 1
std/python/lib/Json.hx

@@ -18,6 +18,6 @@ extern class Json {
 	public static function dumps (x:Dynamic, skipkeys:Bool=false, ensure_ascii:Bool=true, check_circular:Bool=true,
 		allow_nan:Bool=true,
 		cls:Null<Dynamic> = null, indent:Null<String> = null,
-		separators:Null<Tup2<String,String>>, /*default*/def:Null<Dynamic->String> = null, sort_keys:Bool=false, kw:KwArgs = null):String;
+		separators:Null<Tup2<String,String>>, /*default*/def:Null<Dynamic->String> = null, sort_keys:Bool=false, kw:KwArgs<Dynamic> = null):String;
 
 }

+ 23 - 6
tests/unit/src/unit/TestPython.hx

@@ -216,7 +216,7 @@ class TestPython extends Test {
 	}
 
 	function testKwArgsAfterVarArgs () {
-		function test (va:VarArgs, kw:KwArgs) {
+		function test (va:VarArgs, kw:KwArgs<Dynamic>) {
 			var a = va.toArray();
 
 			eq(1,a[0]);
@@ -229,7 +229,7 @@ class TestPython extends Test {
 	}
 
 	function testOptionalVarArgs () {
-		function test (?va:VarArgs, ?kw:KwArgs) {
+		function test (?va:VarArgs, ?kw:KwArgs<Dynamic>) {
 			var a = va.toArray();
 
 			eq(0,a.length);
@@ -238,12 +238,12 @@ class TestPython extends Test {
 	}
 
 	function testOptionalKwArgs () {
-		function test (?kw:KwArgs) eq(0,kw.toDict().length());
+		function test (?kw:KwArgs<Dynamic>) eq(0,kw.toDict().length());
 		test();
 	}
 
 	function testOptionalKwArgsAfterOptionalVarArgs () {
-		function test (?va:VarArgs, ?kw:KwArgs) {
+		function test (?va:VarArgs, ?kw:KwArgs<Dynamic>) {
 			var a = va.toArray();
 
 			eq(1,a[0]);
@@ -254,7 +254,7 @@ class TestPython extends Test {
 		var x = [1,2];
 		test(x);
 
-		function test (?va:VarArgs, ?kw:KwArgs) {
+		function test (?va:VarArgs, ?kw:KwArgs<Dynamic>) {
 			var a = va.toArray();
 			eq(0,a.length);
 			eq(1, kw.get("a",null));
@@ -266,7 +266,7 @@ class TestPython extends Test {
 	}
 
 	function testKwArgs () {
-		function x (args:KwArgs) {
+		function x (args:KwArgs<Dynamic>) {
 			var a = args.get("a", 0);
 			var b = args.get("b", 0);
 			return a + b;
@@ -282,6 +282,23 @@ class TestPython extends Test {
 		eq(8, res2);
 	}
 
+	function testTypedKwArgs () {
+		function x (args:KwArgs<{ a : Int, b : Int}>) {
+			var x = args.typed();
+
+			return x.a + x.b;
+		}
+
+		var a = { a : 1, b : 2};
+		var res = x( a );
+
+		eq(3, res);
+
+		var res = x( { a : 1, b : 2} );
+
+		eq(3, res);
+	}
+
 	function testNonLocal() {
 		try { }
 		catch (e:Dynamic) {

+ 1 - 1
tests/unit/src/unit/issues/Issue2856.hx

@@ -3,7 +3,7 @@ package unit.issues;
 class Issue2856 extends Test {
 	#if python
 	function test() {
-		function x (args:python.KwArgs) {
+		function x (args:python.KwArgs<Dynamic>) {
 			var dict = args.toDict();
 			var acc = [];
 			for (key in dict.keys()) {

+ 1 - 1
tests/unit/src/unit/issues/Issue2980.hx

@@ -3,7 +3,7 @@ package unit.issues;
 class Issue2980 extends Test {
 
 	#if python
-	function a(?args:python.KwArgs) {}
+	function a(?args:python.KwArgs<Dynamic>) {}
     function b(?args:python.VarArgs) {}
 
 	function test() {