Blame third_party/waf/waflib/Utils.py

rpm-build 95f51c
#!/usr/bin/env python
rpm-build 95f51c
# encoding: utf-8
rpm-build 95f51c
# Thomas Nagy, 2005-2018 (ita)
rpm-build 95f51c
rpm-build 95f51c
"""
rpm-build 95f51c
Utilities and platform-specific fixes
rpm-build 95f51c
rpm-build 95f51c
The portability fixes try to provide a consistent behavior of the Waf API
rpm-build 95f51c
through Python versions 2.5 to 3.X and across different platforms (win32, linux, etc)
rpm-build 95f51c
"""
rpm-build 95f51c
rpm-build 95f51c
from __future__ import with_statement
rpm-build 95f51c
rpm-build 95f51c
import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time
rpm-build 95f51c
rpm-build 95f51c
try:
rpm-build 95f51c
	import cPickle
rpm-build 95f51c
except ImportError:
rpm-build 95f51c
	import pickle as cPickle
rpm-build 95f51c
rpm-build 95f51c
# leave this
rpm-build 95f51c
if os.name == 'posix' and sys.version_info[0] < 3:
rpm-build 95f51c
	try:
rpm-build 95f51c
		import subprocess32 as subprocess
rpm-build 95f51c
	except ImportError:
rpm-build 95f51c
		import subprocess
rpm-build 95f51c
else:
rpm-build 95f51c
	import subprocess
rpm-build 95f51c
rpm-build 95f51c
try:
rpm-build 95f51c
	TimeoutExpired = subprocess.TimeoutExpired
rpm-build 95f51c
except AttributeError:
rpm-build 95f51c
	class TimeoutExpired(Exception):
rpm-build 95f51c
		pass
rpm-build 95f51c
rpm-build 95f51c
from collections import deque, defaultdict
rpm-build 95f51c
rpm-build 95f51c
try:
rpm-build 95f51c
	import _winreg as winreg
rpm-build 95f51c
except ImportError:
rpm-build 95f51c
	try:
rpm-build 95f51c
		import winreg
rpm-build 95f51c
	except ImportError:
rpm-build 95f51c
		winreg = None
rpm-build 95f51c
rpm-build 95f51c
from waflib import Errors
rpm-build 95f51c
rpm-build 95f51c
try:
rpm-build 95f51c
	from hashlib import md5
rpm-build 95f51c
except ImportError:
rpm-build 95f51c
	try:
rpm-build 95f51c
		from hashlib import sha1 as md5
rpm-build 95f51c
	except ImportError:
rpm-build 95f51c
		# never fail to enable potential fixes from another module
rpm-build 95f51c
		pass
rpm-build 95f51c
else:
rpm-build 95f51c
	try:
rpm-build 95f51c
		md5().digest()
rpm-build 95f51c
	except ValueError:
rpm-build 95f51c
		# Fips? #2213
rpm-build 95f51c
		from hashlib import sha1 as md5
rpm-build 95f51c
rpm-build 95f51c
try:
rpm-build 95f51c
	import threading
rpm-build 95f51c
except ImportError:
rpm-build 95f51c
	if not 'JOBS' in os.environ:
rpm-build 95f51c
		# no threading :-(
rpm-build 95f51c
		os.environ['JOBS'] = '1'
rpm-build 95f51c
rpm-build 95f51c
	class threading(object):
rpm-build 95f51c
		"""
rpm-build 95f51c
		A fake threading class for platforms lacking the threading module.
rpm-build 95f51c
		Use ``waf -j1`` on those platforms
rpm-build 95f51c
		"""
rpm-build 95f51c
		pass
rpm-build 95f51c
	class Lock(object):
rpm-build 95f51c
		"""Fake Lock class"""
rpm-build 95f51c
		def acquire(self):
rpm-build 95f51c
			pass
rpm-build 95f51c
		def release(self):
rpm-build 95f51c
			pass
rpm-build 95f51c
	threading.Lock = threading.Thread = Lock
rpm-build 95f51c
rpm-build 95f51c
SIG_NIL = 'SIG_NIL_SIG_NIL_'.encode()
rpm-build 95f51c
"""Arbitrary null value for hashes. Modify this value according to the hash function in use"""
rpm-build 95f51c
rpm-build 95f51c
O644 = 420
rpm-build 95f51c
"""Constant representing the permissions for regular files (0644 raises a syntax error on python 3)"""
rpm-build 95f51c
rpm-build 95f51c
O755 = 493
rpm-build 95f51c
"""Constant representing the permissions for executable files (0755 raises a syntax error on python 3)"""
rpm-build 95f51c
rpm-build 95f51c
rot_chr = ['\\', '|', '/', '-']
rpm-build 95f51c
"List of characters to use when displaying the throbber (progress bar)"
rpm-build 95f51c
rpm-build 95f51c
rot_idx = 0
rpm-build 95f51c
"Index of the current throbber character (progress bar)"
rpm-build 95f51c
rpm-build 95f51c
class ordered_iter_dict(dict):
rpm-build 95f51c
	"""Ordered dictionary that provides iteration from the most recently inserted keys first"""
rpm-build 95f51c
	def __init__(self, *k, **kw):
rpm-build 95f51c
		self.lst = deque()
rpm-build 95f51c
		dict.__init__(self, *k, **kw)
rpm-build 95f51c
	def clear(self):
rpm-build 95f51c
		dict.clear(self)
rpm-build 95f51c
		self.lst = deque()
rpm-build 95f51c
	def __setitem__(self, key, value):
rpm-build 95f51c
		if key in dict.keys(self):
rpm-build 95f51c
			self.lst.remove(key)
rpm-build 95f51c
		dict.__setitem__(self, key, value)
rpm-build 95f51c
		self.lst.append(key)
rpm-build 95f51c
	def __delitem__(self, key):
rpm-build 95f51c
		dict.__delitem__(self, key)
rpm-build 95f51c
		try:
rpm-build 95f51c
			self.lst.remove(key)
rpm-build 95f51c
		except ValueError:
rpm-build 95f51c
			pass
rpm-build 95f51c
	def __iter__(self):
rpm-build 95f51c
		return reversed(self.lst)
rpm-build 95f51c
	def keys(self):
rpm-build 95f51c
		return reversed(self.lst)
rpm-build 95f51c
rpm-build 95f51c
class lru_node(object):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Used by :py:class:`waflib.Utils.lru_cache`
rpm-build 95f51c
	"""
rpm-build 95f51c
	__slots__ = ('next', 'prev', 'key', 'val')
rpm-build 95f51c
	def __init__(self):
rpm-build 95f51c
		self.next = self
rpm-build 95f51c
		self.prev = self
rpm-build 95f51c
		self.key = None
rpm-build 95f51c
		self.val = None
rpm-build 95f51c
rpm-build 95f51c
class lru_cache(object):
rpm-build 95f51c
	"""
rpm-build 95f51c
	A simple least-recently used cache with lazy allocation
rpm-build 95f51c
	"""
rpm-build 95f51c
	__slots__ = ('maxlen', 'table', 'head')
rpm-build 95f51c
	def __init__(self, maxlen=100):
rpm-build 95f51c
		self.maxlen = maxlen
rpm-build 95f51c
		"""
rpm-build 95f51c
		Maximum amount of elements in the cache
rpm-build 95f51c
		"""
rpm-build 95f51c
		self.table = {}
rpm-build 95f51c
		"""
rpm-build 95f51c
		Mapping key-value
rpm-build 95f51c
		"""
rpm-build 95f51c
		self.head = lru_node()
rpm-build 95f51c
		self.head.next = self.head
rpm-build 95f51c
		self.head.prev = self.head
rpm-build 95f51c
rpm-build 95f51c
	def __getitem__(self, key):
rpm-build 95f51c
		node = self.table[key]
rpm-build 95f51c
		# assert(key==node.key)
rpm-build 95f51c
		if node is self.head:
rpm-build 95f51c
			return node.val
rpm-build 95f51c
rpm-build 95f51c
		# detach the node found
rpm-build 95f51c
		node.prev.next = node.next
rpm-build 95f51c
		node.next.prev = node.prev
rpm-build 95f51c
rpm-build 95f51c
		# replace the head
rpm-build 95f51c
		node.next = self.head.next
rpm-build 95f51c
		node.prev = self.head
rpm-build 95f51c
		self.head = node.next.prev = node.prev.next = node
rpm-build 95f51c
rpm-build 95f51c
		return node.val
rpm-build 95f51c
rpm-build 95f51c
	def __setitem__(self, key, val):
rpm-build 95f51c
		if key in self.table:
rpm-build 95f51c
			# update the value for an existing key
rpm-build 95f51c
			node = self.table[key]
rpm-build 95f51c
			node.val = val
rpm-build 95f51c
			self.__getitem__(key)
rpm-build 95f51c
		else:
rpm-build 95f51c
			if len(self.table) < self.maxlen:
rpm-build 95f51c
				# the very first item is unused until the maximum is reached
rpm-build 95f51c
				node = lru_node()
rpm-build 95f51c
				node.prev = self.head
rpm-build 95f51c
				node.next = self.head.next
rpm-build 95f51c
				node.prev.next = node.next.prev = node
rpm-build 95f51c
			else:
rpm-build 95f51c
				node = self.head = self.head.next
rpm-build 95f51c
				try:
rpm-build 95f51c
					# that's another key
rpm-build 95f51c
					del self.table[node.key]
rpm-build 95f51c
				except KeyError:
rpm-build 95f51c
					pass
rpm-build 95f51c
rpm-build 95f51c
			node.key = key
rpm-build 95f51c
			node.val = val
rpm-build 95f51c
			self.table[key] = node
rpm-build 95f51c
rpm-build 95f51c
class lazy_generator(object):
rpm-build 95f51c
	def __init__(self, fun, params):
rpm-build 95f51c
		self.fun = fun
rpm-build 95f51c
		self.params = params
rpm-build 95f51c
rpm-build 95f51c
	def __iter__(self):
rpm-build 95f51c
		return self
rpm-build 95f51c
rpm-build 95f51c
	def __next__(self):
rpm-build 95f51c
		try:
rpm-build 95f51c
			it = self.it
rpm-build 95f51c
		except AttributeError:
rpm-build 95f51c
			it = self.it = self.fun(*self.params)
rpm-build 95f51c
		return next(it)
rpm-build 95f51c
rpm-build 95f51c
	next = __next__
rpm-build 95f51c
rpm-build 95f51c
is_win32 = os.sep == '\\' or sys.platform == 'win32' or os.name == 'nt' # msys2
rpm-build 95f51c
"""
rpm-build 95f51c
Whether this system is a Windows series
rpm-build 95f51c
"""
rpm-build 95f51c
rpm-build 95f51c
def readf(fname, m='r', encoding='latin-1'):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Reads an entire file into a string. See also :py:meth:`waflib.Node.Node.readf`::
rpm-build 95f51c
rpm-build 95f51c
		def build(ctx):
rpm-build 95f51c
			from waflib import Utils
rpm-build 95f51c
			txt = Utils.readf(self.path.find_node('wscript').abspath())
rpm-build 95f51c
			txt = ctx.path.find_node('wscript').read()
rpm-build 95f51c
rpm-build 95f51c
	:type  fname: string
rpm-build 95f51c
	:param fname: Path to file
rpm-build 95f51c
	:type  m: string
rpm-build 95f51c
	:param m: Open mode
rpm-build 95f51c
	:type encoding: string
rpm-build 95f51c
	:param encoding: encoding value, only used for python 3
rpm-build 95f51c
	:rtype: string
rpm-build 95f51c
	:return: Content of the file
rpm-build 95f51c
	"""
rpm-build 95f51c
rpm-build 95f51c
	if sys.hexversion > 0x3000000 and not 'b' in m:
rpm-build 95f51c
		m += 'b'
rpm-build 95f51c
		with open(fname, m) as f:
rpm-build 95f51c
			txt = f.read()
rpm-build 95f51c
		if encoding:
rpm-build 95f51c
			txt = txt.decode(encoding)
rpm-build 95f51c
		else:
rpm-build 95f51c
			txt = txt.decode()
rpm-build 95f51c
	else:
rpm-build 95f51c
		with open(fname, m) as f:
rpm-build 95f51c
			txt = f.read()
rpm-build 95f51c
	return txt
rpm-build 95f51c
rpm-build 95f51c
def writef(fname, data, m='w', encoding='latin-1'):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Writes an entire file from a string.
rpm-build 95f51c
	See also :py:meth:`waflib.Node.Node.writef`::
rpm-build 95f51c
rpm-build 95f51c
		def build(ctx):
rpm-build 95f51c
			from waflib import Utils
rpm-build 95f51c
			txt = Utils.writef(self.path.make_node('i_like_kittens').abspath(), 'some data')
rpm-build 95f51c
			self.path.make_node('i_like_kittens').write('some data')
rpm-build 95f51c
rpm-build 95f51c
	:type  fname: string
rpm-build 95f51c
	:param fname: Path to file
rpm-build 95f51c
	:type   data: string
rpm-build 95f51c
	:param  data: The contents to write to the file
rpm-build 95f51c
	:type  m: string
rpm-build 95f51c
	:param m: Open mode
rpm-build 95f51c
	:type encoding: string
rpm-build 95f51c
	:param encoding: encoding value, only used for python 3
rpm-build 95f51c
	"""
rpm-build 95f51c
	if sys.hexversion > 0x3000000 and not 'b' in m:
rpm-build 95f51c
		data = data.encode(encoding)
rpm-build 95f51c
		m += 'b'
rpm-build 95f51c
	with open(fname, m) as f:
rpm-build 95f51c
		f.write(data)
rpm-build 95f51c
rpm-build 95f51c
def h_file(fname):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Computes a hash value for a file by using md5. Use the md5_tstamp
rpm-build 95f51c
	extension to get faster build hashes if necessary.
rpm-build 95f51c
rpm-build 95f51c
	:type fname: string
rpm-build 95f51c
	:param fname: path to the file to hash
rpm-build 95f51c
	:return: hash of the file contents
rpm-build 95f51c
	:rtype: string or bytes
rpm-build 95f51c
	"""
rpm-build 95f51c
	m = md5()
rpm-build 95f51c
	with open(fname, 'rb') as f:
rpm-build 95f51c
		while fname:
rpm-build 95f51c
			fname = f.read(200000)
rpm-build 95f51c
			m.update(fname)
rpm-build 95f51c
	return m.digest()
rpm-build 95f51c
rpm-build 95f51c
def readf_win32(f, m='r', encoding='latin-1'):
rpm-build 95f51c
	flags = os.O_NOINHERIT | os.O_RDONLY
rpm-build 95f51c
	if 'b' in m:
rpm-build 95f51c
		flags |= os.O_BINARY
rpm-build 95f51c
	if '+' in m:
rpm-build 95f51c
		flags |= os.O_RDWR
rpm-build 95f51c
	try:
rpm-build 95f51c
		fd = os.open(f, flags)
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		raise IOError('Cannot read from %r' % f)
rpm-build 95f51c
rpm-build 95f51c
	if sys.hexversion > 0x3000000 and not 'b' in m:
rpm-build 95f51c
		m += 'b'
rpm-build 95f51c
		with os.fdopen(fd, m) as f:
rpm-build 95f51c
			txt = f.read()
rpm-build 95f51c
		if encoding:
rpm-build 95f51c
			txt = txt.decode(encoding)
rpm-build 95f51c
		else:
rpm-build 95f51c
			txt = txt.decode()
rpm-build 95f51c
	else:
rpm-build 95f51c
		with os.fdopen(fd, m) as f:
rpm-build 95f51c
			txt = f.read()
rpm-build 95f51c
	return txt
rpm-build 95f51c
rpm-build 95f51c
def writef_win32(f, data, m='w', encoding='latin-1'):
rpm-build 95f51c
	if sys.hexversion > 0x3000000 and not 'b' in m:
rpm-build 95f51c
		data = data.encode(encoding)
rpm-build 95f51c
		m += 'b'
rpm-build 95f51c
	flags = os.O_CREAT | os.O_TRUNC | os.O_WRONLY | os.O_NOINHERIT
rpm-build 95f51c
	if 'b' in m:
rpm-build 95f51c
		flags |= os.O_BINARY
rpm-build 95f51c
	if '+' in m:
rpm-build 95f51c
		flags |= os.O_RDWR
rpm-build 95f51c
	try:
rpm-build 95f51c
		fd = os.open(f, flags)
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		raise OSError('Cannot write to %r' % f)
rpm-build 95f51c
	with os.fdopen(fd, m) as f:
rpm-build 95f51c
		f.write(data)
rpm-build 95f51c
rpm-build 95f51c
def h_file_win32(fname):
rpm-build 95f51c
	try:
rpm-build 95f51c
		fd = os.open(fname, os.O_BINARY | os.O_RDONLY | os.O_NOINHERIT)
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		raise OSError('Cannot read from %r' % fname)
rpm-build 95f51c
	m = md5()
rpm-build 95f51c
	with os.fdopen(fd, 'rb') as f:
rpm-build 95f51c
		while fname:
rpm-build 95f51c
			fname = f.read(200000)
rpm-build 95f51c
			m.update(fname)
rpm-build 95f51c
	return m.digest()
rpm-build 95f51c
rpm-build 95f51c
# always save these
rpm-build 95f51c
readf_unix = readf
rpm-build 95f51c
writef_unix = writef
rpm-build 95f51c
h_file_unix = h_file
rpm-build 95f51c
if hasattr(os, 'O_NOINHERIT') and sys.hexversion < 0x3040000:
rpm-build 95f51c
	# replace the default functions
rpm-build 95f51c
	readf = readf_win32
rpm-build 95f51c
	writef = writef_win32
rpm-build 95f51c
	h_file = h_file_win32
rpm-build 95f51c
rpm-build 95f51c
try:
rpm-build 95f51c
	x = ''.encode('hex')
rpm-build 95f51c
except LookupError:
rpm-build 95f51c
	import binascii
rpm-build 95f51c
	def to_hex(s):
rpm-build 95f51c
		ret = binascii.hexlify(s)
rpm-build 95f51c
		if not isinstance(ret, str):
rpm-build 95f51c
			ret = ret.decode('utf-8')
rpm-build 95f51c
		return ret
rpm-build 95f51c
else:
rpm-build 95f51c
	def to_hex(s):
rpm-build 95f51c
		return s.encode('hex')
rpm-build 95f51c
rpm-build 95f51c
to_hex.__doc__ = """
rpm-build 95f51c
Return the hexadecimal representation of a string
rpm-build 95f51c
rpm-build 95f51c
:param s: string to convert
rpm-build 95f51c
:type s: string
rpm-build 95f51c
"""
rpm-build 95f51c
rpm-build 95f51c
def listdir_win32(s):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Lists the contents of a folder in a portable manner.
rpm-build 95f51c
	On Win32, returns the list of drive letters: ['C:', 'X:', 'Z:'] when an empty string is given.
rpm-build 95f51c
rpm-build 95f51c
	:type s: string
rpm-build 95f51c
	:param s: a string, which can be empty on Windows
rpm-build 95f51c
	"""
rpm-build 95f51c
	if not s:
rpm-build 95f51c
		try:
rpm-build 95f51c
			import ctypes
rpm-build 95f51c
		except ImportError:
rpm-build 95f51c
			# there is nothing much we can do
rpm-build 95f51c
			return [x + ':\\' for x in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ']
rpm-build 95f51c
		else:
rpm-build 95f51c
			dlen = 4 # length of "?:\\x00"
rpm-build 95f51c
			maxdrives = 26
rpm-build 95f51c
			buf = ctypes.create_string_buffer(maxdrives * dlen)
rpm-build 95f51c
			ndrives = ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives*dlen, ctypes.byref(buf))
rpm-build 95f51c
			return [ str(buf.raw[4*i:4*i+2].decode('ascii')) for i in range(int(ndrives/dlen)) ]
rpm-build 95f51c
rpm-build 95f51c
	if len(s) == 2 and s[1] == ":":
rpm-build 95f51c
		s += os.sep
rpm-build 95f51c
rpm-build 95f51c
	if not os.path.isdir(s):
rpm-build 95f51c
		e = OSError('%s is not a directory' % s)
rpm-build 95f51c
		e.errno = errno.ENOENT
rpm-build 95f51c
		raise e
rpm-build 95f51c
	return os.listdir(s)
rpm-build 95f51c
rpm-build 95f51c
listdir = os.listdir
rpm-build 95f51c
if is_win32:
rpm-build 95f51c
	listdir = listdir_win32
rpm-build 95f51c
rpm-build 95f51c
def num2ver(ver):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Converts a string, tuple or version number into an integer. The number is supposed to have at most 4 digits::
rpm-build 95f51c
rpm-build 95f51c
		from waflib.Utils import num2ver
rpm-build 95f51c
		num2ver('1.3.2') == num2ver((1,3,2)) == num2ver((1,3,2,0))
rpm-build 95f51c
rpm-build 95f51c
	:type ver: string or tuple of numbers
rpm-build 95f51c
	:param ver: a version number
rpm-build 95f51c
	"""
rpm-build 95f51c
	if isinstance(ver, str):
rpm-build 95f51c
		ver = tuple(ver.split('.'))
rpm-build 95f51c
	if isinstance(ver, tuple):
rpm-build 95f51c
		ret = 0
rpm-build 95f51c
		for i in range(4):
rpm-build 95f51c
			if i < len(ver):
rpm-build 95f51c
				ret += 256**(3 - i) * int(ver[i])
rpm-build 95f51c
		return ret
rpm-build 95f51c
	return ver
rpm-build 95f51c
rpm-build 95f51c
def to_list(val):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Converts a string argument to a list by splitting it by spaces.
rpm-build 95f51c
	Returns the object if not a string::
rpm-build 95f51c
rpm-build 95f51c
		from waflib.Utils import to_list
rpm-build 95f51c
		lst = to_list('a b c d')
rpm-build 95f51c
rpm-build 95f51c
	:param val: list of string or space-separated string
rpm-build 95f51c
	:rtype: list
rpm-build 95f51c
	:return: Argument converted to list
rpm-build 95f51c
	"""
rpm-build 95f51c
	if isinstance(val, str):
rpm-build 95f51c
		return val.split()
rpm-build 95f51c
	else:
rpm-build 95f51c
		return val
rpm-build 95f51c
rpm-build 95f51c
def console_encoding():
rpm-build 95f51c
	try:
rpm-build 95f51c
		import ctypes
rpm-build 95f51c
	except ImportError:
rpm-build 95f51c
		pass
rpm-build 95f51c
	else:
rpm-build 95f51c
		try:
rpm-build 95f51c
			codepage = ctypes.windll.kernel32.GetConsoleCP()
rpm-build 95f51c
		except AttributeError:
rpm-build 95f51c
			pass
rpm-build 95f51c
		else:
rpm-build 95f51c
			if codepage:
rpm-build 95f51c
				return 'cp%d' % codepage
rpm-build 95f51c
	return sys.stdout.encoding or ('cp1252' if is_win32 else 'latin-1')
rpm-build 95f51c
rpm-build 95f51c
def split_path_unix(path):
rpm-build 95f51c
	return path.split('/')
rpm-build 95f51c
rpm-build 95f51c
def split_path_cygwin(path):
rpm-build 95f51c
	if path.startswith('//'):
rpm-build 95f51c
		ret = path.split('/')[2:]
rpm-build 95f51c
		ret[0] = '/' + ret[0]
rpm-build 95f51c
		return ret
rpm-build 95f51c
	return path.split('/')
rpm-build 95f51c
rpm-build 95f51c
re_sp = re.compile('[/\\\\]+')
rpm-build 95f51c
def split_path_win32(path):
rpm-build 95f51c
	if path.startswith('\\\\'):
rpm-build 95f51c
		ret = re_sp.split(path)[1:]
rpm-build 95f51c
		ret[0] = '\\\\' + ret[0]
rpm-build 95f51c
		if ret[0] == '\\\\?':
rpm-build 95f51c
			return ret[1:]
rpm-build 95f51c
		return ret
rpm-build 95f51c
	return re_sp.split(path)
rpm-build 95f51c
rpm-build 95f51c
msysroot = None
rpm-build 95f51c
def split_path_msys(path):
rpm-build 95f51c
	if path.startswith(('/', '\\')) and not path.startswith(('//', '\\\\')):
rpm-build 95f51c
		# msys paths can be in the form /usr/bin
rpm-build 95f51c
		global msysroot
rpm-build 95f51c
		if not msysroot:
rpm-build 95f51c
			# msys has python 2.7 or 3, so we can use this
rpm-build 95f51c
			msysroot = subprocess.check_output(['cygpath', '-w', '/']).decode(sys.stdout.encoding or 'latin-1')
rpm-build 95f51c
			msysroot = msysroot.strip()
rpm-build 95f51c
		path = os.path.normpath(msysroot + os.sep + path)
rpm-build 95f51c
	return split_path_win32(path)
rpm-build 95f51c
rpm-build 95f51c
if sys.platform == 'cygwin':
rpm-build 95f51c
	split_path = split_path_cygwin
rpm-build 95f51c
elif is_win32:
rpm-build 95f51c
	# Consider this an MSYSTEM environment if $MSYSTEM is set and python
rpm-build 95f51c
	# reports is executable from a unix like path on a windows host.
rpm-build 95f51c
	if os.environ.get('MSYSTEM') and sys.executable.startswith('/'):
rpm-build 95f51c
		split_path = split_path_msys
rpm-build 95f51c
	else:
rpm-build 95f51c
		split_path = split_path_win32
rpm-build 95f51c
else:
rpm-build 95f51c
	split_path = split_path_unix
rpm-build 95f51c
rpm-build 95f51c
split_path.__doc__ = """
rpm-build 95f51c
Splits a path by / or \\; do not confuse this function with with ``os.path.split``
rpm-build 95f51c
rpm-build 95f51c
:type  path: string
rpm-build 95f51c
:param path: path to split
rpm-build 95f51c
:return:     list of string
rpm-build 95f51c
"""
rpm-build 95f51c
rpm-build 95f51c
def check_dir(path):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Ensures that a directory exists (similar to ``mkdir -p``).
rpm-build 95f51c
rpm-build 95f51c
	:type  path: string
rpm-build 95f51c
	:param path: Path to directory
rpm-build 95f51c
	:raises: :py:class:`waflib.Errors.WafError` if the folder cannot be added.
rpm-build 95f51c
	"""
rpm-build 95f51c
	if not os.path.isdir(path):
rpm-build 95f51c
		try:
rpm-build 95f51c
			os.makedirs(path)
rpm-build 95f51c
		except OSError as e:
rpm-build 95f51c
			if not os.path.isdir(path):
rpm-build 95f51c
				raise Errors.WafError('Cannot create the folder %r' % path, ex=e)
rpm-build 95f51c
rpm-build 95f51c
def check_exe(name, env=None):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Ensures that a program exists
rpm-build 95f51c
rpm-build 95f51c
	:type name: string
rpm-build 95f51c
	:param name: path to the program
rpm-build 95f51c
	:param env: configuration object
rpm-build 95f51c
	:type env: :py:class:`waflib.ConfigSet.ConfigSet`
rpm-build 95f51c
	:return: path of the program or None
rpm-build 95f51c
	:raises: :py:class:`waflib.Errors.WafError` if the folder cannot be added.
rpm-build 95f51c
	"""
rpm-build 95f51c
	if not name:
rpm-build 95f51c
		raise ValueError('Cannot execute an empty string!')
rpm-build 95f51c
	def is_exe(fpath):
rpm-build 95f51c
		return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
rpm-build 95f51c
rpm-build 95f51c
	fpath, fname = os.path.split(name)
rpm-build 95f51c
	if fpath and is_exe(name):
rpm-build 95f51c
		return os.path.abspath(name)
rpm-build 95f51c
	else:
rpm-build 95f51c
		env = env or os.environ
rpm-build 95f51c
		for path in env['PATH'].split(os.pathsep):
rpm-build 95f51c
			path = path.strip('"')
rpm-build 95f51c
			exe_file = os.path.join(path, name)
rpm-build 95f51c
			if is_exe(exe_file):
rpm-build 95f51c
				return os.path.abspath(exe_file)
rpm-build 95f51c
	return None
rpm-build 95f51c
rpm-build 95f51c
def def_attrs(cls, **kw):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Sets default attributes on a class instance
rpm-build 95f51c
rpm-build 95f51c
	:type cls: class
rpm-build 95f51c
	:param cls: the class to update the given attributes in.
rpm-build 95f51c
	:type kw: dict
rpm-build 95f51c
	:param kw: dictionary of attributes names and values.
rpm-build 95f51c
	"""
rpm-build 95f51c
	for k, v in kw.items():
rpm-build 95f51c
		if not hasattr(cls, k):
rpm-build 95f51c
			setattr(cls, k, v)
rpm-build 95f51c
rpm-build 95f51c
def quote_define_name(s):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Converts a string into an identifier suitable for C defines.
rpm-build 95f51c
rpm-build 95f51c
	:type  s: string
rpm-build 95f51c
	:param s: String to convert
rpm-build 95f51c
	:rtype: string
rpm-build 95f51c
	:return: Identifier suitable for C defines
rpm-build 95f51c
	"""
rpm-build 95f51c
	fu = re.sub('[^a-zA-Z0-9]', '_', s)
rpm-build 95f51c
	fu = re.sub('_+', '_', fu)
rpm-build 95f51c
	fu = fu.upper()
rpm-build 95f51c
	return fu
rpm-build 95f51c
rpm-build 95f51c
re_sh = re.compile('\\s|\'|"')
rpm-build 95f51c
"""
rpm-build 95f51c
Regexp used for shell_escape below
rpm-build 95f51c
"""
rpm-build 95f51c
rpm-build 95f51c
def shell_escape(cmd):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Escapes a command:
rpm-build 95f51c
	['ls', '-l', 'arg space'] -> ls -l 'arg space'
rpm-build 95f51c
	"""
rpm-build 95f51c
	if isinstance(cmd, str):
rpm-build 95f51c
		return cmd
rpm-build 95f51c
	return ' '.join(repr(x) if re_sh.search(x) else x for x in cmd)
rpm-build 95f51c
rpm-build 95f51c
def h_list(lst):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Hashes lists of ordered data.
rpm-build 95f51c
rpm-build 95f51c
	Using hash(tup) for tuples would be much more efficient,
rpm-build 95f51c
	but Python now enforces hash randomization
rpm-build 95f51c
rpm-build 95f51c
	:param lst: list to hash
rpm-build 95f51c
	:type lst: list of strings
rpm-build 95f51c
	:return: hash of the list
rpm-build 95f51c
	"""
rpm-build 95f51c
	return md5(repr(lst).encode()).digest()
rpm-build 95f51c
rpm-build 95f51c
if sys.hexversion < 0x3000000:
rpm-build 95f51c
	def h_list_python2(lst):
rpm-build 95f51c
		return md5(repr(lst)).digest()
rpm-build 95f51c
	h_list_python2.__doc__ = h_list.__doc__
rpm-build 95f51c
	h_list = h_list_python2
rpm-build 95f51c
rpm-build 95f51c
def h_fun(fun):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Hash functions
rpm-build 95f51c
rpm-build 95f51c
	:param fun: function to hash
rpm-build 95f51c
	:type  fun: function
rpm-build 95f51c
	:return: hash of the function
rpm-build 95f51c
	:rtype: string or bytes
rpm-build 95f51c
	"""
rpm-build 95f51c
	try:
rpm-build 95f51c
		return fun.code
rpm-build 95f51c
	except AttributeError:
rpm-build 95f51c
		if isinstance(fun, functools.partial):
rpm-build 95f51c
			code = list(fun.args)
rpm-build 95f51c
			# The method items() provides a sequence of tuples where the first element
rpm-build 95f51c
			# represents an optional argument of the partial function application
rpm-build 95f51c
			#
rpm-build 95f51c
			# The sorting result outcome will be consistent because:
rpm-build 95f51c
			# 1. tuples are compared in order of their elements
rpm-build 95f51c
			# 2. optional argument namess are unique
rpm-build 95f51c
			code.extend(sorted(fun.keywords.items()))
rpm-build 95f51c
			code.append(h_fun(fun.func))
rpm-build 95f51c
			fun.code = h_list(code)
rpm-build 95f51c
			return fun.code
rpm-build 95f51c
		try:
rpm-build 95f51c
			h = inspect.getsource(fun)
rpm-build 95f51c
		except EnvironmentError:
rpm-build 95f51c
			h = 'nocode'
rpm-build 95f51c
		try:
rpm-build 95f51c
			fun.code = h
rpm-build 95f51c
		except AttributeError:
rpm-build 95f51c
			pass
rpm-build 95f51c
		return h
rpm-build 95f51c
rpm-build 95f51c
def h_cmd(ins):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Hashes objects recursively
rpm-build 95f51c
rpm-build 95f51c
	:param ins: input object
rpm-build 95f51c
	:type ins: string or list or tuple or function
rpm-build 95f51c
	:rtype: string or bytes
rpm-build 95f51c
	"""
rpm-build 95f51c
	# this function is not meant to be particularly fast
rpm-build 95f51c
	if isinstance(ins, str):
rpm-build 95f51c
		# a command is either a string
rpm-build 95f51c
		ret = ins
rpm-build 95f51c
	elif isinstance(ins, list) or isinstance(ins, tuple):
rpm-build 95f51c
		# or a list of functions/strings
rpm-build 95f51c
		ret = str([h_cmd(x) for x in ins])
rpm-build 95f51c
	else:
rpm-build 95f51c
		# or just a python function
rpm-build 95f51c
		ret = str(h_fun(ins))
rpm-build 95f51c
	if sys.hexversion > 0x3000000:
rpm-build 95f51c
		ret = ret.encode('latin-1', 'xmlcharrefreplace')
rpm-build 95f51c
	return ret
rpm-build 95f51c
rpm-build 95f51c
reg_subst = re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}")
rpm-build 95f51c
def subst_vars(expr, params):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Replaces ${VAR} with the value of VAR taken from a dict or a config set::
rpm-build 95f51c
rpm-build 95f51c
		from waflib import Utils
rpm-build 95f51c
		s = Utils.subst_vars('${PREFIX}/bin', env)
rpm-build 95f51c
rpm-build 95f51c
	:type  expr: string
rpm-build 95f51c
	:param expr: String to perform substitution on
rpm-build 95f51c
	:param params: Dictionary or config set to look up variable values.
rpm-build 95f51c
	"""
rpm-build 95f51c
	def repl_var(m):
rpm-build 95f51c
		if m.group(1):
rpm-build 95f51c
			return '\\'
rpm-build 95f51c
		if m.group(2):
rpm-build 95f51c
			return '$'
rpm-build 95f51c
		try:
rpm-build 95f51c
			# ConfigSet instances may contain lists
rpm-build 95f51c
			return params.get_flat(m.group(3))
rpm-build 95f51c
		except AttributeError:
rpm-build 95f51c
			return params[m.group(3)]
rpm-build 95f51c
		# if you get a TypeError, it means that 'expr' is not a string...
rpm-build 95f51c
		# Utils.subst_vars(None, env)  will not work
rpm-build 95f51c
	return reg_subst.sub(repl_var, expr)
rpm-build 95f51c
rpm-build 95f51c
def destos_to_binfmt(key):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Returns the binary format based on the unversioned platform name,
rpm-build 95f51c
	and defaults to ``elf`` if nothing is found.
rpm-build 95f51c
rpm-build 95f51c
	:param key: platform name
rpm-build 95f51c
	:type  key: string
rpm-build 95f51c
	:return: string representing the binary format
rpm-build 95f51c
	"""
rpm-build 95f51c
	if key == 'darwin':
rpm-build 95f51c
		return 'mac-o'
rpm-build 95f51c
	elif key in ('win32', 'cygwin', 'uwin', 'msys'):
rpm-build 95f51c
		return 'pe'
rpm-build 95f51c
	return 'elf'
rpm-build 95f51c
rpm-build 95f51c
def unversioned_sys_platform():
rpm-build 95f51c
	"""
rpm-build 95f51c
	Returns the unversioned platform name.
rpm-build 95f51c
	Some Python platform names contain versions, that depend on
rpm-build 95f51c
	the build environment, e.g. linux2, freebsd6, etc.
rpm-build 95f51c
	This returns the name without the version number. Exceptions are
rpm-build 95f51c
	os2 and win32, which are returned verbatim.
rpm-build 95f51c
rpm-build 95f51c
	:rtype: string
rpm-build 95f51c
	:return: Unversioned platform name
rpm-build 95f51c
	"""
rpm-build 95f51c
	s = sys.platform
rpm-build 95f51c
	if s.startswith('java'):
rpm-build 95f51c
		# The real OS is hidden under the JVM.
rpm-build 95f51c
		from java.lang import System
rpm-build 95f51c
		s = System.getProperty('os.name')
rpm-build 95f51c
		# see http://lopica.sourceforge.net/os.html for a list of possible values
rpm-build 95f51c
		if s == 'Mac OS X':
rpm-build 95f51c
			return 'darwin'
rpm-build 95f51c
		elif s.startswith('Windows '):
rpm-build 95f51c
			return 'win32'
rpm-build 95f51c
		elif s == 'OS/2':
rpm-build 95f51c
			return 'os2'
rpm-build 95f51c
		elif s == 'HP-UX':
rpm-build 95f51c
			return 'hp-ux'
rpm-build 95f51c
		elif s in ('SunOS', 'Solaris'):
rpm-build 95f51c
			return 'sunos'
rpm-build 95f51c
		else: s = s.lower()
rpm-build 95f51c
rpm-build 95f51c
	# powerpc == darwin for our purposes
rpm-build 95f51c
	if s == 'powerpc':
rpm-build 95f51c
		return 'darwin'
rpm-build 95f51c
	if s == 'win32' or s == 'os2':
rpm-build 95f51c
		return s
rpm-build 95f51c
	if s == 'cli' and os.name == 'nt':
rpm-build 95f51c
		# ironpython is only on windows as far as we know
rpm-build 95f51c
		return 'win32'
rpm-build 95f51c
	return re.split(r'\d+$', s)[0]
rpm-build 95f51c
rpm-build 95f51c
def nada(*k, **kw):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Does nothing
rpm-build 95f51c
rpm-build 95f51c
	:return: None
rpm-build 95f51c
	"""
rpm-build 95f51c
	pass
rpm-build 95f51c
rpm-build 95f51c
class Timer(object):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Simple object for timing the execution of commands.
rpm-build 95f51c
	Its string representation is the duration::
rpm-build 95f51c
rpm-build 95f51c
		from waflib.Utils import Timer
rpm-build 95f51c
		timer = Timer()
rpm-build 95f51c
		a_few_operations()
rpm-build 95f51c
		s = str(timer)
rpm-build 95f51c
	"""
rpm-build 95f51c
	def __init__(self):
rpm-build 95f51c
		self.start_time = self.now()
rpm-build 95f51c
rpm-build 95f51c
	def __str__(self):
rpm-build 95f51c
		delta = self.now() - self.start_time
rpm-build 95f51c
		if not isinstance(delta, datetime.timedelta):
rpm-build 95f51c
			delta = datetime.timedelta(seconds=delta)
rpm-build 95f51c
		days = delta.days
rpm-build 95f51c
		hours, rem = divmod(delta.seconds, 3600)
rpm-build 95f51c
		minutes, seconds = divmod(rem, 60)
rpm-build 95f51c
		seconds += delta.microseconds * 1e-6
rpm-build 95f51c
		result = ''
rpm-build 95f51c
		if days:
rpm-build 95f51c
			result += '%dd' % days
rpm-build 95f51c
		if days or hours:
rpm-build 95f51c
			result += '%dh' % hours
rpm-build 95f51c
		if days or hours or minutes:
rpm-build 95f51c
			result += '%dm' % minutes
rpm-build 95f51c
		return '%s%.3fs' % (result, seconds)
rpm-build 95f51c
rpm-build 95f51c
	def now(self):
rpm-build 95f51c
		return datetime.datetime.utcnow()
rpm-build 95f51c
rpm-build 95f51c
	if hasattr(time, 'perf_counter'):
rpm-build 95f51c
		def now(self):
rpm-build 95f51c
			return time.perf_counter()
rpm-build 95f51c
rpm-build 95f51c
def read_la_file(path):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Reads property files, used by msvc.py
rpm-build 95f51c
rpm-build 95f51c
	:param path: file to read
rpm-build 95f51c
	:type path: string
rpm-build 95f51c
	"""
rpm-build 95f51c
	sp = re.compile(r'^([^=]+)=\'(.*)\'$')
rpm-build 95f51c
	dc = {}
rpm-build 95f51c
	for line in readf(path).splitlines():
rpm-build 95f51c
		try:
rpm-build 95f51c
			_, left, right, _ = sp.split(line.strip())
rpm-build 95f51c
			dc[left] = right
rpm-build 95f51c
		except ValueError:
rpm-build 95f51c
			pass
rpm-build 95f51c
	return dc
rpm-build 95f51c
rpm-build 95f51c
def run_once(fun):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Decorator: let a function cache its results, use like this::
rpm-build 95f51c
rpm-build 95f51c
		@run_once
rpm-build 95f51c
		def foo(k):
rpm-build 95f51c
			return 345*2343
rpm-build 95f51c
rpm-build 95f51c
	.. note:: in practice this can cause memory leaks, prefer a :py:class:`waflib.Utils.lru_cache`
rpm-build 95f51c
rpm-build 95f51c
	:param fun: function to execute
rpm-build 95f51c
	:type fun: function
rpm-build 95f51c
	:return: the return value of the function executed
rpm-build 95f51c
	"""
rpm-build 95f51c
	cache = {}
rpm-build 95f51c
	def wrap(*k):
rpm-build 95f51c
		try:
rpm-build 95f51c
			return cache[k]
rpm-build 95f51c
		except KeyError:
rpm-build 95f51c
			ret = fun(*k)
rpm-build 95f51c
			cache[k] = ret
rpm-build 95f51c
			return ret
rpm-build 95f51c
	wrap.__cache__ = cache
rpm-build 95f51c
	wrap.__name__ = fun.__name__
rpm-build 95f51c
	return wrap
rpm-build 95f51c
rpm-build 95f51c
def get_registry_app_path(key, filename):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Returns the value of a registry key for an executable
rpm-build 95f51c
rpm-build 95f51c
	:type key: string
rpm-build 95f51c
	:type filename: list of string
rpm-build 95f51c
	"""
rpm-build 95f51c
	if not winreg:
rpm-build 95f51c
		return None
rpm-build 95f51c
	try:
rpm-build 95f51c
		result = winreg.QueryValue(key, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe" % filename[0])
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		pass
rpm-build 95f51c
	else:
rpm-build 95f51c
		if os.path.isfile(result):
rpm-build 95f51c
			return result
rpm-build 95f51c
rpm-build 95f51c
def lib64():
rpm-build 95f51c
	"""
rpm-build 95f51c
	Guess the default ``/usr/lib`` extension for 64-bit applications
rpm-build 95f51c
rpm-build 95f51c
	:return: '64' or ''
rpm-build 95f51c
	:rtype: string
rpm-build 95f51c
	"""
rpm-build 95f51c
	# default settings for /usr/lib
rpm-build 95f51c
	if os.sep == '/':
rpm-build 95f51c
		if platform.architecture()[0] == '64bit':
rpm-build 95f51c
			if os.path.exists('/usr/lib64') and not os.path.exists('/usr/lib32'):
rpm-build 95f51c
				return '64'
rpm-build 95f51c
	return ''
rpm-build 95f51c
rpm-build 95f51c
def sane_path(p):
rpm-build 95f51c
	# private function for the time being!
rpm-build 95f51c
	return os.path.abspath(os.path.expanduser(p))
rpm-build 95f51c
rpm-build 95f51c
process_pool = []
rpm-build 95f51c
"""
rpm-build 95f51c
List of processes started to execute sub-process commands
rpm-build 95f51c
"""
rpm-build 95f51c
rpm-build 95f51c
def get_process():
rpm-build 95f51c
	"""
rpm-build 95f51c
	Returns a process object that can execute commands as sub-processes
rpm-build 95f51c
rpm-build 95f51c
	:rtype: subprocess.Popen
rpm-build 95f51c
	"""
rpm-build 95f51c
	try:
rpm-build 95f51c
		return process_pool.pop()
rpm-build 95f51c
	except IndexError:
rpm-build 95f51c
		filepath = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'processor.py'
rpm-build 95f51c
		cmd = [sys.executable, '-c', readf(filepath)]
rpm-build 95f51c
		return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0, close_fds=not is_win32)
rpm-build 95f51c
rpm-build 95f51c
def run_prefork_process(cmd, kwargs, cargs):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Delegates process execution to a pre-forked process instance.
rpm-build 95f51c
	"""
rpm-build 95f51c
	if not 'env' in kwargs:
rpm-build 95f51c
		kwargs['env'] = dict(os.environ)
rpm-build 95f51c
	try:
rpm-build 95f51c
		obj = base64.b64encode(cPickle.dumps([cmd, kwargs, cargs]))
rpm-build 95f51c
	except (TypeError, AttributeError):
rpm-build 95f51c
		return run_regular_process(cmd, kwargs, cargs)
rpm-build 95f51c
rpm-build 95f51c
	proc = get_process()
rpm-build 95f51c
	if not proc:
rpm-build 95f51c
		return run_regular_process(cmd, kwargs, cargs)
rpm-build 95f51c
rpm-build 95f51c
	proc.stdin.write(obj)
rpm-build 95f51c
	proc.stdin.write('\n'.encode())
rpm-build 95f51c
	proc.stdin.flush()
rpm-build 95f51c
	obj = proc.stdout.readline()
rpm-build 95f51c
	if not obj:
rpm-build 95f51c
		raise OSError('Preforked sub-process %r died' % proc.pid)
rpm-build 95f51c
rpm-build 95f51c
	process_pool.append(proc)
rpm-build 95f51c
	lst = cPickle.loads(base64.b64decode(obj))
rpm-build 95f51c
	# Jython wrapper failures (bash/execvp)
rpm-build 95f51c
	assert len(lst) == 5
rpm-build 95f51c
	ret, out, err, ex, trace = lst
rpm-build 95f51c
	if ex:
rpm-build 95f51c
		if ex == 'OSError':
rpm-build 95f51c
			raise OSError(trace)
rpm-build 95f51c
		elif ex == 'ValueError':
rpm-build 95f51c
			raise ValueError(trace)
rpm-build 95f51c
		elif ex == 'TimeoutExpired':
rpm-build 95f51c
			exc = TimeoutExpired(cmd, timeout=cargs['timeout'], output=out)
rpm-build 95f51c
			exc.stderr = err
rpm-build 95f51c
			raise exc
rpm-build 95f51c
		else:
rpm-build 95f51c
			raise Exception(trace)
rpm-build 95f51c
	return ret, out, err
rpm-build 95f51c
rpm-build 95f51c
def lchown(path, user=-1, group=-1):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Change the owner/group of a path, raises an OSError if the
rpm-build 95f51c
	ownership change fails.
rpm-build 95f51c
rpm-build 95f51c
	:param user: user to change
rpm-build 95f51c
	:type user: int or str
rpm-build 95f51c
	:param group: group to change
rpm-build 95f51c
	:type group: int or str
rpm-build 95f51c
	"""
rpm-build 95f51c
	if isinstance(user, str):
rpm-build 95f51c
		import pwd
rpm-build 95f51c
		entry = pwd.getpwnam(user)
rpm-build 95f51c
		if not entry:
rpm-build 95f51c
			raise OSError('Unknown user %r' % user)
rpm-build 95f51c
		user = entry[2]
rpm-build 95f51c
	if isinstance(group, str):
rpm-build 95f51c
		import grp
rpm-build 95f51c
		entry = grp.getgrnam(group)
rpm-build 95f51c
		if not entry:
rpm-build 95f51c
			raise OSError('Unknown group %r' % group)
rpm-build 95f51c
		group = entry[2]
rpm-build 95f51c
	return os.lchown(path, user, group)
rpm-build 95f51c
rpm-build 95f51c
def run_regular_process(cmd, kwargs, cargs={}):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Executes a subprocess command by using subprocess.Popen
rpm-build 95f51c
	"""
rpm-build 95f51c
	proc = subprocess.Popen(cmd, **kwargs)
rpm-build 95f51c
	if kwargs.get('stdout') or kwargs.get('stderr'):
rpm-build 95f51c
		try:
rpm-build 95f51c
			out, err = proc.communicate(**cargs)
rpm-build 95f51c
		except TimeoutExpired:
rpm-build 95f51c
			if kwargs.get('start_new_session') and hasattr(os, 'killpg'):
rpm-build 95f51c
				os.killpg(proc.pid, signal.SIGKILL)
rpm-build 95f51c
			else:
rpm-build 95f51c
				proc.kill()
rpm-build 95f51c
			out, err = proc.communicate()
rpm-build 95f51c
			exc = TimeoutExpired(proc.args, timeout=cargs['timeout'], output=out)
rpm-build 95f51c
			exc.stderr = err
rpm-build 95f51c
			raise exc
rpm-build 95f51c
		status = proc.returncode
rpm-build 95f51c
	else:
rpm-build 95f51c
		out, err = (None, None)
rpm-build 95f51c
		try:
rpm-build 95f51c
			status = proc.wait(**cargs)
rpm-build 95f51c
		except TimeoutExpired as e:
rpm-build 95f51c
			if kwargs.get('start_new_session') and hasattr(os, 'killpg'):
rpm-build 95f51c
				os.killpg(proc.pid, signal.SIGKILL)
rpm-build 95f51c
			else:
rpm-build 95f51c
				proc.kill()
rpm-build 95f51c
			proc.wait()
rpm-build 95f51c
			raise e
rpm-build 95f51c
	return status, out, err
rpm-build 95f51c
rpm-build 95f51c
def run_process(cmd, kwargs, cargs={}):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Executes a subprocess by using a pre-forked process when possible
rpm-build 95f51c
	or falling back to subprocess.Popen. See :py:func:`waflib.Utils.run_prefork_process`
rpm-build 95f51c
	and :py:func:`waflib.Utils.run_regular_process`
rpm-build 95f51c
	"""
rpm-build 95f51c
	if kwargs.get('stdout') and kwargs.get('stderr'):
rpm-build 95f51c
		return run_prefork_process(cmd, kwargs, cargs)
rpm-build 95f51c
	else:
rpm-build 95f51c
		return run_regular_process(cmd, kwargs, cargs)
rpm-build 95f51c
rpm-build 95f51c
def alloc_process_pool(n, force=False):
rpm-build 95f51c
	"""
rpm-build 95f51c
	Allocates an amount of processes to the default pool so its size is at least *n*.
rpm-build 95f51c
	It is useful to call this function early so that the pre-forked
rpm-build 95f51c
	processes use as little memory as possible.
rpm-build 95f51c
rpm-build 95f51c
	:param n: pool size
rpm-build 95f51c
	:type n: integer
rpm-build 95f51c
	:param force: if True then *n* more processes are added to the existing pool
rpm-build 95f51c
	:type force: bool
rpm-build 95f51c
	"""
rpm-build 95f51c
	# mandatory on python2, unnecessary on python >= 3.2
rpm-build 95f51c
	global run_process, get_process, alloc_process_pool
rpm-build 95f51c
	if not force:
rpm-build 95f51c
		n = max(n - len(process_pool), 0)
rpm-build 95f51c
	try:
rpm-build 95f51c
		lst = [get_process() for x in range(n)]
rpm-build 95f51c
	except OSError:
rpm-build 95f51c
		run_process = run_regular_process
rpm-build 95f51c
		get_process = alloc_process_pool = nada
rpm-build 95f51c
	else:
rpm-build 95f51c
		for x in lst:
rpm-build 95f51c
			process_pool.append(x)
rpm-build 95f51c
rpm-build 95f51c
def atexit_pool():
rpm-build 95f51c
	for k in process_pool:
rpm-build 95f51c
		try:
rpm-build 95f51c
			os.kill(k.pid, 9)
rpm-build 95f51c
		except OSError:
rpm-build 95f51c
			pass
rpm-build 95f51c
		else:
rpm-build 95f51c
			k.wait()
rpm-build 95f51c
# see #1889
rpm-build 95f51c
if (sys.hexversion<0x207000f and not is_win32) or sys.hexversion>=0x306000f:
rpm-build 95f51c
	atexit.register(atexit_pool)
rpm-build 95f51c
rpm-build 95f51c
if os.environ.get('WAF_NO_PREFORK') or sys.platform == 'cli' or not sys.executable:
rpm-build 95f51c
	run_process = run_regular_process
rpm-build 95f51c
	get_process = alloc_process_pool = nada
rpm-build 95f51c