Hello,
I’m Geoffroy and I’m new to this forum. I’m experimenting with python target this days especially with external libraries.
Some external libraries are working with decorators (ie: Flask, Bottle, Click…)
I used the HelloWorld of Click for learning purposes.
import click
@click.command()
@click.option('--name', prompt='Your name', help='The person to greet.')
def hello(name):
print('Hello' + name)
How would you output such code? I experimented with externs without success. I omitted the name parameter to focus on the @command decorator and then focus on the @option decorator.
import haxe.Constraints.Function;
@:pythonImport("click")
extern class Click{
function new();
function command<T:Function>():T;
}
class Main {
static function main():Void {
var click = new Click();
click.command()(hello);
}
static function hello() {
trace("Hello");
}
}
Outputs
import click as Click
class Main:
__slots__ = ()
@staticmethod
def main():
click = Click()
click.command()(Main.hello)
@staticmethod
def hello():
print("Hello")
And return:
Traceback (most recent call last):
File ".\TestHX.py", line 34, in <module>
Main.main()
File ".\TestHX.py", line 12, in main
click = Click()
TypeError: 'module' object is not callable
Any idea on how to handle such libraries?
I’m still a beginner, so please excuse me if my understanding of all of this is wrong.
Hi @supergeoff, I think you’re on the right track.
I don’t know if haxe has special support for python decorators built-in, but you can define them as function generators in the externs - more or less like you did -, and then use them with standard haxe syntax.
Thanks Azrafe7, I will look a it in detail. As for the “verbosity” i was thinking macro to clean things up.
I’ll check that.
Very much appreciated!
Have a nice day.
Edit: Here’s the result of using Click
Click.hx (externs)
package click;
import haxe.Constraints.Function;
import python.VarArgs;
import python.KwArgs;
@:pythonImport("click")
extern class Click {
static function command():Function;
static function option(v:Dynamic, ?kvargs:KwArgs<Dynamic>):Function;
}
Usage:
import click.*;
import haxe.Constraints.Function;
class Click_HelloWorld {
public static function main():Void {
Click.command()(Click.option("--name", {"default": "Geoff", "help": "Name of the greeting."})(hello))();
}
public static function hello(name:String):Void {
trace("Hello " + name);
}
}
I’ll edit with a less verbose/clearer option using macros. It will be a good exercise for me.
Again, thx for the help. Regards;
Edit: Here’s a way to make it less verbose (well in my opinion at least) using macros.
package macros;
import haxe.macro.Expr;
class Click {
macro public static function command(f:Expr, v:Dynamic, ?opt:Dynamic):Expr {
return macro Click.command()(Click.option(${v}, ${opt})(${f}))();
}
}
Usage:
import click.*;
import macros.Click as C;
class Click_HelloWorld {
public static function main():Void {
C.command(hello, "--name", {"prompt": true, "help": "Specify the name for the greeting."});
}
public static function hello(name:String):Void {
trace("Hello " + name);
}
}
I’m going to try what’s happening when you need to chain different options. I’ll keep posting here in case it can be of any help for someone with the same questions as me.