mirror of
https://github.com/boostorg/build.git
synced 2026-02-17 13:42:14 +00:00
Implemented a mechanism for parameter translation from bjam to python
signatures.
This allows to expose the same interface to Jamfiles as before, e.g.
rule toolset.flags ( rule variable condition * : values * )
and use natural interface in the Python side, where, 'rule', 'variable',
'condition' and 'values' are parameters, and the first two of them
will get string, not list of strings.
[SVN r64158]
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
|
||||
import re
|
||||
|
||||
from b2.util import set, utility
|
||||
from b2.util import set, utility, bjam_signature
|
||||
from b2.util.utility import add_grist, get_grist, ungrist, replace_grist, to_seq
|
||||
from b2.exceptions import *
|
||||
|
||||
@@ -83,6 +83,7 @@ def enumerate ():
|
||||
|
||||
# FIXME: prepare-test/finish-test?
|
||||
|
||||
@bjam_signature((["name"], ["values", "*"], ["attributes", "*"]))
|
||||
def feature (name, values, attributes = []):
|
||||
""" Declares a new feature with the given name, values, and attributes.
|
||||
name: the feature name
|
||||
|
||||
@@ -978,7 +978,6 @@ attribute is allowed only for top-level 'project' invocations""")
|
||||
"Tool module '%s' does not define the 'init' method" % toolset[0])
|
||||
m.init(*args)
|
||||
|
||||
|
||||
def import_(self, name, names_to_import=None, local_names=None):
|
||||
|
||||
name = name[0]
|
||||
@@ -991,7 +990,10 @@ attribute is allowed only for top-level 'project' invocations""")
|
||||
for f in m.__dict__:
|
||||
v = m.__dict__[f]
|
||||
if callable(v):
|
||||
bjam.import_rule(jamfile_module, name + "." + f, v)
|
||||
if hasattr(v, "bjam_signature"):
|
||||
bjam.import_rule(jamfile_module, name + "." + f, v, v.bjam_signature)
|
||||
else:
|
||||
bjam.import_rule(jamfile_module, name + "." + f, v)
|
||||
|
||||
if names_to_import:
|
||||
if not local_names:
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
import feature, property, generators, property_set
|
||||
from b2.util.utility import *
|
||||
from b2.util import set
|
||||
from b2.util import set, bjam_signature
|
||||
|
||||
__re_split_last_segment = re.compile (r'^(.+)\.([^\.])*')
|
||||
__re_two_ampersands = re.compile ('(&&)')
|
||||
@@ -87,7 +87,9 @@ def normalize_condition (property_sets):
|
||||
# FIXME push-checking-for-flags-module ....
|
||||
# FIXME: investigate existing uses of 'hack-hack' parameter
|
||||
# in jam code.
|
||||
|
||||
|
||||
@bjam_signature((["rule_or_module", "variable_name", "condition", "*"],
|
||||
["values", "*"]))
|
||||
def flags (rule_or_module, variable_name, condition, values = []):
|
||||
""" Specifies the flags (variables) that must be set on targets under certain
|
||||
conditions, described by arguments.
|
||||
|
||||
@@ -1902,8 +1902,12 @@ PyObject* bjam_call( PyObject * self, PyObject * args )
|
||||
|
||||
|
||||
/*
|
||||
* Accepts three arguments: module name, rule name and Python callable. Creates
|
||||
* a bjam rule with the specified name in the specified module, which will
|
||||
* Accepts four arguments:
|
||||
* - module name
|
||||
* - rule name,
|
||||
* - Python callable.
|
||||
* - (optional) bjam language function signature.
|
||||
* Creates a bjam rule with the specified name in the specified module, which will
|
||||
* invoke the Python callable.
|
||||
*/
|
||||
|
||||
@@ -1912,10 +1916,12 @@ PyObject * bjam_import_rule( PyObject * self, PyObject * args )
|
||||
char * module;
|
||||
char * rule;
|
||||
PyObject * func;
|
||||
PyObject * bjam_signature = NULL;
|
||||
module_t * m;
|
||||
RULE * r;
|
||||
|
||||
if ( !PyArg_ParseTuple( args, "ssO:import_rule", &module, &rule, &func ) )
|
||||
if ( !PyArg_ParseTuple( args, "ssO|O:import_rule",
|
||||
&module, &rule, &func, &bjam_signature ) )
|
||||
return NULL;
|
||||
|
||||
if ( !PyCallable_Check( func ) )
|
||||
@@ -1932,6 +1938,22 @@ PyObject * bjam_import_rule( PyObject * self, PyObject * args )
|
||||
Py_INCREF( func );
|
||||
|
||||
r->python_function = func;
|
||||
r->arguments = 0;
|
||||
|
||||
if (bjam_signature)
|
||||
{
|
||||
argument_list * arg_list = args_new();
|
||||
Py_ssize_t i;
|
||||
|
||||
Py_ssize_t s = PySequence_Size (bjam_signature);
|
||||
for (i = 0; i < s; ++i)
|
||||
{
|
||||
PyObject* v = PySequence_GetItem (bjam_signature, i);
|
||||
lol_add(arg_list->data, list_from_python (v));
|
||||
Py_DECREF(v);
|
||||
}
|
||||
r->arguments = arg_list;
|
||||
}
|
||||
|
||||
Py_INCREF( Py_None );
|
||||
return Py_None;
|
||||
|
||||
@@ -707,6 +707,7 @@ collect_arguments( RULE* rule, FRAME* frame )
|
||||
LIST* value = 0;
|
||||
char modifier;
|
||||
LIST* arg_name = formal; /* hold the argument name for type checking */
|
||||
int multiple = 0;
|
||||
|
||||
/* Stop now if a variable number of arguments are specified */
|
||||
if ( name[0] == '*' && name[1] == 0 )
|
||||
@@ -722,6 +723,7 @@ collect_arguments( RULE* rule, FRAME* frame )
|
||||
case '+':
|
||||
case '*':
|
||||
value = list_copy( 0, actual );
|
||||
multiple = 1;
|
||||
actual = 0;
|
||||
/* skip an extra element for the modifier */
|
||||
formal = formal->next;
|
||||
@@ -738,7 +740,8 @@ collect_arguments( RULE* rule, FRAME* frame )
|
||||
}
|
||||
}
|
||||
|
||||
locals = addsettings( locals, VAR_SET, name, value );
|
||||
locals = addsettings(locals, VAR_SET, name, value);
|
||||
locals->multiple = multiple;
|
||||
type_check( type_name, value, frame, rule, arg_name );
|
||||
type_name = 0;
|
||||
}
|
||||
@@ -764,28 +767,58 @@ static LIST*
|
||||
call_python_function(RULE* r, FRAME* frame)
|
||||
{
|
||||
LIST * result = 0;
|
||||
PyObject * arguments = PyTuple_New( frame->args->count );
|
||||
PyObject * arguments = 0;
|
||||
PyObject * kw = NULL;
|
||||
int i ;
|
||||
PyObject * py_result;
|
||||
|
||||
for ( i = 0; i < frame->args->count; ++i )
|
||||
if (r->arguments)
|
||||
{
|
||||
PyObject * arg = PyList_New(0);
|
||||
LIST* l = lol_get( frame->args, i);
|
||||
SETTINGS * args;
|
||||
|
||||
for ( ; l; l = l->next )
|
||||
arguments = PyTuple_New(0);
|
||||
kw = PyDict_New();
|
||||
|
||||
for (args = collect_arguments(r, frame); args; args = args->next)
|
||||
{
|
||||
PyObject * v = PyString_FromString(l->string);
|
||||
PyList_Append( arg, v );
|
||||
Py_DECREF(v);
|
||||
PyObject *key = PyString_FromString(args->symbol);
|
||||
PyObject *value = 0;
|
||||
if (args->multiple)
|
||||
value = list_to_python(args->value);
|
||||
else {
|
||||
if (args->value)
|
||||
value = PyString_FromString(args->value->string);
|
||||
}
|
||||
|
||||
if (value)
|
||||
PyDict_SetItem(kw, key, value);
|
||||
Py_DECREF(key);
|
||||
Py_XDECREF(value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
arguments = PyTuple_New( frame->args->count );
|
||||
for ( i = 0; i < frame->args->count; ++i )
|
||||
{
|
||||
PyObject * arg = PyList_New(0);
|
||||
LIST* l = lol_get( frame->args, i);
|
||||
|
||||
for ( ; l; l = l->next )
|
||||
{
|
||||
PyObject * v = PyString_FromString(l->string);
|
||||
PyList_Append( arg, v );
|
||||
Py_DECREF(v);
|
||||
}
|
||||
/* Steals reference to 'arg' */
|
||||
PyTuple_SetItem( arguments, i, arg );
|
||||
}
|
||||
/* Steals reference to 'arg' */
|
||||
PyTuple_SetItem( arguments, i, arg );
|
||||
}
|
||||
|
||||
frame_before_python_call = frame;
|
||||
py_result = PyObject_CallObject( r->python_function, arguments );
|
||||
Py_DECREF( arguments );
|
||||
py_result = PyObject_Call( r->python_function, arguments, kw );
|
||||
Py_DECREF(arguments);
|
||||
Py_XDECREF(kw);
|
||||
if ( py_result != NULL )
|
||||
{
|
||||
if ( PyList_Check( py_result ) )
|
||||
|
||||
@@ -303,3 +303,37 @@ void lol_print( LOL * lol )
|
||||
list_print( lol->list[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
PyObject *list_to_python(LIST *l)
|
||||
{
|
||||
PyObject *result = PyList_New(0);
|
||||
|
||||
for (; l; l = l->next)
|
||||
{
|
||||
PyObject* s = PyString_FromString(l->string);
|
||||
PyList_Append(result, s);
|
||||
Py_DECREF(s);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
LIST *list_from_python(PyObject *l)
|
||||
{
|
||||
LIST * result = 0;
|
||||
|
||||
Py_ssize_t i, n;
|
||||
n = PySequence_Size(l);
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
PyObject *v = PySequence_GetItem(l, i);
|
||||
result = list_new (result, newstr (PyString_AsString(v)));
|
||||
Py_DECREF(v);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -45,6 +45,10 @@
|
||||
#ifndef LISTS_DWA20011022_H
|
||||
# define LISTS_DWA20011022_H
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* LIST - list of strings
|
||||
*/
|
||||
@@ -93,5 +97,12 @@ LIST * lol_get( LOL *lol, int i );
|
||||
void lol_print( LOL *lol );
|
||||
void lol_build( LOL* lol, char** elements );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
PyObject *list_to_python(LIST *l);
|
||||
LIST *list_from_python(PyObject *l);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -421,6 +421,7 @@ SETTINGS * addsettings( SETTINGS * head, int flag, char * symbol, LIST * value )
|
||||
v->symbol = newstr( symbol );
|
||||
v->value = value;
|
||||
v->next = head;
|
||||
v->multiple = 0;
|
||||
head = v;
|
||||
}
|
||||
else if ( flag == VAR_APPEND )
|
||||
|
||||
@@ -119,6 +119,7 @@ struct _settings
|
||||
SETTINGS * next;
|
||||
char * symbol; /* symbol name for var_set() */
|
||||
LIST * value; /* symbol value for var_set() */
|
||||
int multiple;
|
||||
};
|
||||
|
||||
/* TARGETS - a chain of TARGETs. */
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
def bjam_signature(s):
|
||||
|
||||
def wrap(f):
|
||||
f.bjam_signature = s
|
||||
return f
|
||||
|
||||
return wrap
|
||||
|
||||
Reference in New Issue
Block a user