diff options
Diffstat (limited to 'jam-files/boost-build/util/__init__.py')
-rw-r--r-- | jam-files/boost-build/util/__init__.py | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/jam-files/boost-build/util/__init__.py b/jam-files/boost-build/util/__init__.py new file mode 100644 index 00000000..f80fe70e --- /dev/null +++ b/jam-files/boost-build/util/__init__.py @@ -0,0 +1,136 @@ + +import bjam +import re +import types + +# Decorator the specifies bjam-side prototype for a Python function +def bjam_signature(s): + + def wrap(f): + f.bjam_signature = s + return f + + return wrap + +def metatarget(f): + + f.bjam_signature = (["name"], ["sources", "*"], ["requirements", "*"], + ["default_build", "*"], ["usage_requirements", "*"]) + return f + +class cached(object): + + def __init__(self, function): + self.function = function + self.cache = {} + + def __call__(self, *args): + try: + return self.cache[args] + except KeyError: + v = self.function(*args) + self.cache[args] = v + return v + + def __get__(self, instance, type): + return types.MethodType(self, instance, type) + +def unquote(s): + if s and s[0] == '"' and s[-1] == '"': + return s[1:-1] + else: + return s + +_extract_jamfile_and_rule = re.compile("(Jamfile<.*>)%(.*)") + +def qualify_jam_action(action_name, context_module): + + if action_name.startswith("###"): + # Callable exported from Python. Don't touch + return action_name + elif _extract_jamfile_and_rule.match(action_name): + # Rule is already in indirect format + return action_name + else: + ix = action_name.find('.') + if ix != -1 and action_name[:ix] == context_module: + return context_module + '%' + action_name[ix+1:] + + return context_module + '%' + action_name + + +def set_jam_action(name, *args): + + m = _extract_jamfile_and_rule.match(name) + if m: + args = ("set-update-action-in-module", m.group(1), m.group(2)) + args + else: + args = ("set-update-action", name) + args + + return bjam.call(*args) + + +def call_jam_function(name, *args): + + m = _extract_jamfile_and_rule.match(name) + if m: + args = ("call-in-module", m.group(1), m.group(2)) + args + return bjam.call(*args) + else: + return bjam.call(*((name,) + args)) + +__value_id = 0 +__python_to_jam = {} +__jam_to_python = {} + +def value_to_jam(value, methods=False): + """Makes a token to refer to a Python value inside Jam language code. + + The token is merely a string that can be passed around in Jam code and + eventually passed back. For example, we might want to pass PropertySet + instance to a tag function and it might eventually call back + to virtual_target.add_suffix_and_prefix, passing the same instance. + + For values that are classes, we'll also make class methods callable + from Jam. + + Note that this is necessary to make a bit more of existing Jamfiles work. + This trick should not be used to much, or else the performance benefits of + Python port will be eaten. + """ + + global __value_id + + r = __python_to_jam.get(value, None) + if r: + return r + + exported_name = '###_' + str(__value_id) + __value_id = __value_id + 1 + __python_to_jam[value] = exported_name + __jam_to_python[exported_name] = value + + if methods and type(value) == types.InstanceType: + for field_name in dir(value): + field = getattr(value, field_name) + if callable(field) and not field_name.startswith("__"): + bjam.import_rule("", exported_name + "." + field_name, field) + + return exported_name + +def record_jam_to_value_mapping(jam_value, python_value): + __jam_to_python[jam_value] = python_value + +def jam_to_value_maybe(jam_value): + + if type(jam_value) == type(""): + return __jam_to_python.get(jam_value, jam_value) + else: + return jam_value + +def stem(filename): + i = filename.find('.') + if i != -1: + return filename[0:i] + else: + return filename |