Skip to content

Instantly share code, notes, and snippets.

@zmughal
Last active October 2, 2022 19:56
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zmughal/56525c7ad0ca5ba47293c020fc6aec2c to your computer and use it in GitHub Desktop.
Save zmughal/56525c7ad0ca5ba47293c020fc6aec2c to your computer and use it in GitHub Desktop.
#!/usr/bin/env perl
# PODNAME: inline-python-named-args
# ABSTRACT: Example of passing named args to Python via Inline::Python
use strict;
use warnings;
use 5.16.3;
use Test2::V0;
use Inline Python => <<'END_OF_PYTHON_CODE';
def py_call_wrapper(callable, args, kwargs):
return callable(*args, **kwargs)
# Interface
def get_sbom_of_package (
package_name = None,
target_path = None,
):
assert package_name is not None
assert target_path is not None
print ( package_name, target_path )
return package_name
def pos_and_named (
first_arg,
n1 = None,
n2 = None,
):
assert first_arg is not None
assert n1 is not None
assert n2 is not None
return first_arg + n1 + n2
def pos_then_named (
first_arg,
second_arg,
*,
n1 = None,
n2 = None,
):
assert first_arg is not None
assert second_arg is not None
assert n1 is not None
assert n2 is not None
return first_arg + second_arg + n1 + n2
def no_pos_just_named (
*,
n1 = None,
n2 = None,
):
assert n1 is not None
assert n2 is not None
return "n1 = {} and n2 = {}".format(n1, n2)
END_OF_PYTHON_CODE
my $package = 'thePackage';
my $target_path = $ENV{HOME};
use List::Util qw(pairmap unpairs);
use List::SomeUtils qw(part);
sub kw_pairs {
@_ % 2 == 0 or die "Named arguments need pairs of name and value";
my @kw_pairs = pairmap { bless [$a, $b], 'PyKwArgs' } @_;
}
# idea taken from PerlX::ArraySkip
sub kw :prototype(@) { ( kw_pairs(@_[0,1]), @_[2..$#_] ) }
sub python_call_with_named_args {
my ($callable, @args) = @_;
my ($pos, $named) = part { $_->isa('PyKwArgs') } @args;
my %named_unpacked = unpairs @$named;
py_call_wrapper(
Inline::Python::py_eval($callable, 0),
($pos // []),
\%named_unpacked,
);
}
is python_call_with_named_args(
get_sbom_of_package =>
kw package_name => $package,
kw target_path => $target_path
), $package, 'just kwargs';
is python_call_with_named_args(
pos_and_named =>
'Does ',
kw n2 => 'work?',
kw n1 => 'it ',
), 'Does it work?', 'positional args and kwargs';
is python_call_with_named_args(
pos_and_named =>
'Does ',
'it really ',
'work?'
), 'Does it really work?', 'just positional args';
is python_call_with_named_args(
pos_then_named =>
'Yes, ',
'it ',
kw n1 => 'does ',
kw n2 => 'work',
), 'Yes, it does work', 'kwargs must be passed as kwargs, not positional';
is python_call_with_named_args(
no_pos_just_named =>
kw n1 => 'hello',
kw n2 => 'world',
), 'n1 = hello and n2 = world', 'no positionals allowed, just named';
done_testing;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment