summaryrefslogtreecommitdiffstats
path: root/build/pymake/pymake/util.py
blob: c63f930cc229abd12ad0fa7e594882287c2c41a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import os

class MakeError(Exception):
    def __init__(self, message, loc=None):
        self.msg = message
        self.loc = loc

    def __str__(self):
        locstr = ''
        if self.loc is not None:
            locstr = "%s:" % (self.loc,)

        return "%s%s" % (locstr, self.msg)

def normaljoin(path, suffix):
    """
    Combine the given path with the suffix, and normalize if necessary to shrink the path to avoid hitting path length limits
    """
    result = os.path.join(path, suffix)
    if len(result) > 255:
        result = os.path.normpath(result)
    return result

def joiniter(fd, it):
    """
    Given an iterator that returns strings, write the words with a space in between each.
    """
    
    it = iter(it)
    for i in it:
        fd.write(i)
        break

    for i in it:
        fd.write(' ')
        fd.write(i)

def checkmsyscompat():
    """For msys compatibility on windows, honor the SHELL environment variable,
    and if $MSYSTEM == MINGW32, run commands through $SHELL -c instead of
    letting Python use the system shell."""
    if 'SHELL' in os.environ:
        shell = os.environ['SHELL']
    elif 'MOZILLABUILD' in os.environ:
        shell = os.environ['MOZILLABUILD'] + '/msys/bin/sh.exe'
    elif 'COMSPEC' in os.environ:
        shell = os.environ['COMSPEC']
    else:
        raise DataError("Can't find a suitable shell!")

    msys = False
    if 'MSYSTEM' in os.environ and os.environ['MSYSTEM'] == 'MINGW32':
        msys = True
        if not shell.lower().endswith(".exe"):
            shell += ".exe"
    return (shell, msys)

if hasattr(str, 'partition'):
    def strpartition(str, token):
        return str.partition(token)

    def strrpartition(str, token):
        return str.rpartition(token)

else:
    def strpartition(str, token):
        """Python 2.4 compatible str.partition"""

        offset = str.find(token)
        if offset == -1:
            return str, '', ''

        return str[:offset], token, str[offset + len(token):]

    def strrpartition(str, token):
        """Python 2.4 compatible str.rpartition"""

        offset = str.rfind(token)
        if offset == -1:
            return '', '', str

        return str[:offset], token, str[offset + len(token):]

try:
    from __builtin__ import any
except ImportError:
    def any(it):
        for i in it:
            if i:
                return True
        return False

class _MostUsedItem(object):
    __slots__ = ('key', 'o', 'count')

    def __init__(self, key):
        self.key = key
        self.o = None
        self.count = 1

    def __repr__(self):
        return "MostUsedItem(key=%r, count=%i, o=%r)" % (self.key, self.count, self.o)

class MostUsedCache(object):
    def __init__(self, capacity, creationfunc, verifyfunc):
        self.capacity = capacity
        self.cfunc = creationfunc
        self.vfunc = verifyfunc

        self.d = {}
        self.active = [] # lazily sorted!

    def setactive(self, item):
        if item in self.active:
            return

        if len(self.active) == self.capacity:
            self.active.sort(key=lambda i: i.count)
            old = self.active.pop(0)
            old.o = None
            # print "Evicting %s" % old.key

        self.active.append(item)

    def get(self, key):
        item = self.d.get(key, None)
        if item is None:
            item = _MostUsedItem(key)
            self.d[key] = item
        else:
            item.count += 1

        if item.o is not None and self.vfunc(key, item.o):
            return item.o

        item.o = self.cfunc(key)
        self.setactive(item)
        return item.o

    def verify(self):
        for k, v in self.d.iteritems():
            if v.o:
                assert v in self.active
            else:
                assert v not in self.active

    def debugitems(self):
        l = [i.key for i in self.active]
        l.sort()
        return l