Imported Upstream version 1.57.0
[platform/upstream/boost.git] / tools / build / src / util / __init__.py
1
2 import bjam
3 import re
4 import types
5
6 # Decorator the specifies bjam-side prototype for a Python function
7 def bjam_signature(s):
8
9     def wrap(f):       
10         f.bjam_signature = s
11         return f
12
13     return wrap
14
15 def metatarget(f):
16
17     f.bjam_signature = (["name"], ["sources", "*"], ["requirements", "*"],
18                         ["default_build", "*"], ["usage_requirements", "*"])
19     return f
20
21 class cached(object):
22
23     def __init__(self, function):
24         self.function = function
25         self.cache = {}
26
27     def __call__(self, *args):
28         try:
29             return self.cache[args]
30         except KeyError:
31             v = self.function(*args)
32             self.cache[args] = v
33             return v
34
35     def __get__(self, instance, type):
36         return types.MethodType(self, instance, type)
37
38 def unquote(s):
39     if s and s[0] == '"' and s[-1] == '"':
40         return s[1:-1]
41     else:
42         return s
43
44 _extract_jamfile_and_rule = re.compile("(Jamfile<.*>)%(.*)")
45
46 def qualify_jam_action(action_name, context_module):
47
48     if action_name.startswith("###"):
49         # Callable exported from Python. Don't touch
50         return action_name
51     elif _extract_jamfile_and_rule.match(action_name):
52         # Rule is already in indirect format
53         return action_name
54     else:
55         ix = action_name.find('.')
56         if ix != -1 and action_name[:ix] == context_module:
57             return context_module + '%' + action_name[ix+1:]
58         
59         return context_module + '%' + action_name        
60     
61
62 def set_jam_action(name, *args):
63
64     m = _extract_jamfile_and_rule.match(name)
65     if m:
66         args = ("set-update-action-in-module", m.group(1), m.group(2)) + args
67     else:
68         args = ("set-update-action", name) + args
69
70     return bjam.call(*args)
71
72
73 def call_jam_function(name, *args):
74
75     m = _extract_jamfile_and_rule.match(name)
76     if m:
77         args = ("call-in-module", m.group(1), m.group(2)) + args
78         return bjam.call(*args)
79     else:
80         return bjam.call(*((name,) + args))
81
82 __value_id = 0
83 __python_to_jam = {}
84 __jam_to_python = {}
85
86 def value_to_jam(value, methods=False):
87     """Makes a token to refer to a Python value inside Jam language code.
88
89     The token is merely a string that can be passed around in Jam code and
90     eventually passed back. For example, we might want to pass PropertySet
91     instance to a tag function and it might eventually call back
92     to virtual_target.add_suffix_and_prefix, passing the same instance.
93
94     For values that are classes, we'll also make class methods callable
95     from Jam.
96
97     Note that this is necessary to make a bit more of existing Jamfiles work.
98     This trick should not be used to much, or else the performance benefits of
99     Python port will be eaten.
100     """
101
102     global __value_id
103
104     r = __python_to_jam.get(value, None)
105     if r:
106         return r
107
108     exported_name = '###_' + str(__value_id)
109     __value_id = __value_id + 1
110     __python_to_jam[value] = exported_name
111     __jam_to_python[exported_name] = value
112
113     if methods and type(value) == types.InstanceType:
114         for field_name in dir(value):
115             field = getattr(value, field_name)
116             if callable(field) and not field_name.startswith("__"):
117                 bjam.import_rule("", exported_name + "." + field_name, field)
118
119     return exported_name
120
121 def record_jam_to_value_mapping(jam_value, python_value):
122     __jam_to_python[jam_value] = python_value
123
124 def jam_to_value_maybe(jam_value):
125
126     if type(jam_value) == type(""):
127         return __jam_to_python.get(jam_value, jam_value)
128     else:
129         return jam_value
130
131 def stem(filename):
132     i = filename.find('.')
133     if i != -1:
134         return filename[0:i]
135     else:
136         return filename