1 # >>sys.stderr, This Source Code Form is subject to the terms of the Mozilla Public
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 '''Utility methods to be used by python build infrastructure.
14 class LockFile(object):
15 '''LockFile is used by the lockFile method to hold the lock.
17 This object should not be used directly, but only through
18 the lockFile method below.
20 def __init__(self
, lockfile
):
21 self
.lockfile
= lockfile
25 os
.remove(self
.lockfile
)
28 if e
.errno
== errno
.EACCES
:
29 # another process probably has the file open, we'll retry.
30 # just a short sleep since we want to drop the lock ASAP
31 # (but we need to let some other process close the file first)
34 # re-raise unknown errors
37 def lockFile(lockfile
, max_wait
= 600):
38 '''Create and hold a lockfile of the given name, with the given timeout.
40 To release the lock, delete the returned object.
44 fd
= os
.open(lockfile
, os
.O_EXCL | os
.O_RDWR | os
.O_CREAT
)
45 # we created the lockfile, so we're the owner
48 if (e
.errno
== errno
.EEXIST
or
49 (sys
.platform
== "win32" and e
.errno
== errno
.EACCES
)):
56 # the lock file exists, try to stat it to get its age
57 # and read its contents to report the owner PID
58 f
= open(lockfile
, "r")
60 except EnvironmentError as e
:
61 if e
.errno
== errno
.ENOENT
or e
.errno
== errno
.EACCES
:
62 # we didn't create the lockfile, so it did exist, but it's
63 # gone now. Just try again
65 sys
.exit("{0} exists but stat() failed: {1}"
66 .format(lockfile
, e
.strerror
))
68 # we didn't create the lockfile and it's still there, check
70 now
= int(time
.time())
71 if now
- s
[stat
.ST_MTIME
] > max_wait
:
72 pid
= f
.readline().rstrip()
73 sys
.exit("{0} has been locked for more than "
74 "{1} seconds (PID {2})".format(lockfile
, max_wait
, pid
))
76 # it's not been locked too long, wait a while and retry
80 # if we get here. we have the lockfile. Convert the os.open file
81 # descriptor into a Python file object and record our PID in it
83 f
= os
.fdopen(fd
, "w")
84 f
.write("{0}\n".format(os
.getpid()))
86 return LockFile(lockfile
)
88 class pushback_iter(object):
89 '''Utility iterator that can deal with pushed back elements.
91 This behaves like a regular iterable, just that you can call
93 to get the given item as next item in the iteration.
95 def __init__(self
, iterable
):
96 self
.it
= iter(iterable
)
102 def __nonzero__(self
):
107 self
.pushed_back
.insert(0, self
.it
.next())
108 except StopIteration:
115 return self
.pushed_back
.pop()
116 return self
.it
.next()
118 def pushback(self
, item
):
119 self
.pushed_back
.append(item
)