diff options
Diffstat (limited to 'waflib/Utils.py')
-rw-r--r-- | waflib/Utils.py | 615 |
1 files changed, 615 insertions, 0 deletions
diff --git a/waflib/Utils.py b/waflib/Utils.py new file mode 100644 index 0000000..924d1f1 --- /dev/null +++ b/waflib/Utils.py @@ -0,0 +1,615 @@ +#! /usr/bin/env python +# encoding: utf-8 +# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file + +from __future__ import with_statement +import atexit,os,sys,errno,inspect,re,datetime,platform,base64,signal,functools,time +try: + import cPickle +except ImportError: + import pickle as cPickle +if os.name=='posix'and sys.version_info[0]<3: + try: + import subprocess32 as subprocess + except ImportError: + import subprocess +else: + import subprocess +try: + TimeoutExpired=subprocess.TimeoutExpired +except AttributeError: + class TimeoutExpired(Exception): + pass +from collections import deque,defaultdict +try: + import _winreg as winreg +except ImportError: + try: + import winreg + except ImportError: + winreg=None +from waflib import Errors +try: + from hashlib import md5 +except ImportError: + try: + from md5 import md5 + except ImportError: + pass +try: + import threading +except ImportError: + if not'JOBS'in os.environ: + os.environ['JOBS']='1' + class threading(object): + pass + class Lock(object): + def acquire(self): + pass + def release(self): + pass + threading.Lock=threading.Thread=Lock +SIG_NIL='SIG_NIL_SIG_NIL_'.encode() +O644=420 +O755=493 +rot_chr=['\\','|','/','-'] +rot_idx=0 +class ordered_iter_dict(dict): + def __init__(self,*k,**kw): + self.lst=deque() + dict.__init__(self,*k,**kw) + def clear(self): + dict.clear(self) + self.lst=deque() + def __setitem__(self,key,value): + if key in dict.keys(self): + self.lst.remove(key) + dict.__setitem__(self,key,value) + self.lst.append(key) + def __delitem__(self,key): + dict.__delitem__(self,key) + try: + self.lst.remove(key) + except ValueError: + pass + def __iter__(self): + return reversed(self.lst) + def keys(self): + return reversed(self.lst) +class lru_node(object): + __slots__=('next','prev','key','val') + def __init__(self): + self.next=self + self.prev=self + self.key=None + self.val=None +class lru_cache(object): + __slots__=('maxlen','table','head') + def __init__(self,maxlen=100): + self.maxlen=maxlen + self.table={} + self.head=lru_node() + self.head.next=self.head + self.head.prev=self.head + def __getitem__(self,key): + node=self.table[key] + if node is self.head: + return node.val + node.prev.next=node.next + node.next.prev=node.prev + node.next=self.head.next + node.prev=self.head + self.head=node.next.prev=node.prev.next=node + return node.val + def __setitem__(self,key,val): + if key in self.table: + node=self.table[key] + node.val=val + self.__getitem__(key) + else: + if len(self.table)<self.maxlen: + node=lru_node() + node.prev=self.head + node.next=self.head.next + node.prev.next=node.next.prev=node + else: + node=self.head=self.head.next + try: + del self.table[node.key] + except KeyError: + pass + node.key=key + node.val=val + self.table[key]=node +class lazy_generator(object): + def __init__(self,fun,params): + self.fun=fun + self.params=params + def __iter__(self): + return self + def __next__(self): + try: + it=self.it + except AttributeError: + it=self.it=self.fun(*self.params) + return next(it) + next=__next__ +is_win32=os.sep=='\\'or sys.platform=='win32' +def readf(fname,m='r',encoding='latin-1'): + if sys.hexversion>0x3000000 and not'b'in m: + m+='b' + with open(fname,m)as f: + txt=f.read() + if encoding: + txt=txt.decode(encoding) + else: + txt=txt.decode() + else: + with open(fname,m)as f: + txt=f.read() + return txt +def writef(fname,data,m='w',encoding='latin-1'): + if sys.hexversion>0x3000000 and not'b'in m: + data=data.encode(encoding) + m+='b' + with open(fname,m)as f: + f.write(data) +def h_file(fname): + m=md5() + with open(fname,'rb')as f: + while fname: + fname=f.read(200000) + m.update(fname) + return m.digest() +def readf_win32(f,m='r',encoding='latin-1'): + flags=os.O_NOINHERIT|os.O_RDONLY + if'b'in m: + flags|=os.O_BINARY + if'+'in m: + flags|=os.O_RDWR + try: + fd=os.open(f,flags) + except OSError: + raise IOError('Cannot read from %r'%f) + if sys.hexversion>0x3000000 and not'b'in m: + m+='b' + with os.fdopen(fd,m)as f: + txt=f.read() + if encoding: + txt=txt.decode(encoding) + else: + txt=txt.decode() + else: + with os.fdopen(fd,m)as f: + txt=f.read() + return txt +def writef_win32(f,data,m='w',encoding='latin-1'): + if sys.hexversion>0x3000000 and not'b'in m: + data=data.encode(encoding) + m+='b' + flags=os.O_CREAT|os.O_TRUNC|os.O_WRONLY|os.O_NOINHERIT + if'b'in m: + flags|=os.O_BINARY + if'+'in m: + flags|=os.O_RDWR + try: + fd=os.open(f,flags) + except OSError: + raise OSError('Cannot write to %r'%f) + with os.fdopen(fd,m)as f: + f.write(data) +def h_file_win32(fname): + try: + fd=os.open(fname,os.O_BINARY|os.O_RDONLY|os.O_NOINHERIT) + except OSError: + raise OSError('Cannot read from %r'%fname) + m=md5() + with os.fdopen(fd,'rb')as f: + while fname: + fname=f.read(200000) + m.update(fname) + return m.digest() +readf_unix=readf +writef_unix=writef +h_file_unix=h_file +if hasattr(os,'O_NOINHERIT')and sys.hexversion<0x3040000: + readf=readf_win32 + writef=writef_win32 + h_file=h_file_win32 +try: + x=''.encode('hex') +except LookupError: + import binascii + def to_hex(s): + ret=binascii.hexlify(s) + if not isinstance(ret,str): + ret=ret.decode('utf-8') + return ret +else: + def to_hex(s): + return s.encode('hex') +to_hex.__doc__=""" +Return the hexadecimal representation of a string + +:param s: string to convert +:type s: string +""" +def listdir_win32(s): + if not s: + try: + import ctypes + except ImportError: + return[x+':\\'for x in'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] + else: + dlen=4 + maxdrives=26 + buf=ctypes.create_string_buffer(maxdrives*dlen) + ndrives=ctypes.windll.kernel32.GetLogicalDriveStringsA(maxdrives*dlen,ctypes.byref(buf)) + return[str(buf.raw[4*i:4*i+2].decode('ascii'))for i in range(int(ndrives/dlen))] + if len(s)==2 and s[1]==":": + s+=os.sep + if not os.path.isdir(s): + e=OSError('%s is not a directory'%s) + e.errno=errno.ENOENT + raise e + return os.listdir(s) +listdir=os.listdir +if is_win32: + listdir=listdir_win32 +def num2ver(ver): + if isinstance(ver,str): + ver=tuple(ver.split('.')) + if isinstance(ver,tuple): + ret=0 + for i in range(4): + if i<len(ver): + ret+=256**(3-i)*int(ver[i]) + return ret + return ver +def to_list(val): + if isinstance(val,str): + return val.split() + else: + return val +def console_encoding(): + try: + import ctypes + except ImportError: + pass + else: + try: + codepage=ctypes.windll.kernel32.GetConsoleCP() + except AttributeError: + pass + else: + if codepage: + return'cp%d'%codepage + return sys.stdout.encoding or('cp1252'if is_win32 else'latin-1') +def split_path_unix(path): + return path.split('/') +def split_path_cygwin(path): + if path.startswith('//'): + ret=path.split('/')[2:] + ret[0]='/'+ret[0] + return ret + return path.split('/') +re_sp=re.compile('[/\\\\]+') +def split_path_win32(path): + if path.startswith('\\\\'): + ret=re_sp.split(path)[1:] + ret[0]='\\\\'+ret[0] + if ret[0]=='\\\\?': + return ret[1:] + return ret + return re_sp.split(path) +msysroot=None +def split_path_msys(path): + if path.startswith(('/','\\'))and not path.startswith(('//','\\\\')): + global msysroot + if not msysroot: + msysroot=subprocess.check_output(['cygpath','-w','/']).decode(sys.stdout.encoding or'latin-1') + msysroot=msysroot.strip() + path=os.path.normpath(msysroot+os.sep+path) + return split_path_win32(path) +if sys.platform=='cygwin': + split_path=split_path_cygwin +elif is_win32: + if os.environ.get('MSYSTEM'): + split_path=split_path_msys + else: + split_path=split_path_win32 +else: + split_path=split_path_unix +split_path.__doc__=""" +Splits a path by / or \\; do not confuse this function with with ``os.path.split`` + +:type path: string +:param path: path to split +:return: list of string +""" +def check_dir(path): + if not os.path.isdir(path): + try: + os.makedirs(path) + except OSError as e: + if not os.path.isdir(path): + raise Errors.WafError('Cannot create the folder %r'%path,ex=e) +def check_exe(name,env=None): + if not name: + raise ValueError('Cannot execute an empty string!') + def is_exe(fpath): + return os.path.isfile(fpath)and os.access(fpath,os.X_OK) + fpath,fname=os.path.split(name) + if fpath and is_exe(name): + return os.path.abspath(name) + else: + env=env or os.environ + for path in env['PATH'].split(os.pathsep): + path=path.strip('"') + exe_file=os.path.join(path,name) + if is_exe(exe_file): + return os.path.abspath(exe_file) + return None +def def_attrs(cls,**kw): + for k,v in kw.items(): + if not hasattr(cls,k): + setattr(cls,k,v) +def quote_define_name(s): + fu=re.sub('[^a-zA-Z0-9]','_',s) + fu=re.sub('_+','_',fu) + fu=fu.upper() + return fu +re_sh=re.compile('\\s|\'|"') +def shell_escape(cmd): + if isinstance(cmd,str): + return cmd + return' '.join(repr(x)if re_sh.search(x)else x for x in cmd) +def h_list(lst): + return md5(repr(lst).encode()).digest() +def h_fun(fun): + try: + return fun.code + except AttributeError: + if isinstance(fun,functools.partial): + code=list(fun.args) + code.extend(sorted(fun.keywords.items())) + code.append(h_fun(fun.func)) + fun.code=h_list(code) + return fun.code + try: + h=inspect.getsource(fun) + except EnvironmentError: + h='nocode' + try: + fun.code=h + except AttributeError: + pass + return h +def h_cmd(ins): + if isinstance(ins,str): + ret=ins + elif isinstance(ins,list)or isinstance(ins,tuple): + ret=str([h_cmd(x)for x in ins]) + else: + ret=str(h_fun(ins)) + if sys.hexversion>0x3000000: + ret=ret.encode('latin-1','xmlcharrefreplace') + return ret +reg_subst=re.compile(r"(\\\\)|(\$\$)|\$\{([^}]+)\}") +def subst_vars(expr,params): + def repl_var(m): + if m.group(1): + return'\\' + if m.group(2): + return'$' + try: + return params.get_flat(m.group(3)) + except AttributeError: + return params[m.group(3)] + return reg_subst.sub(repl_var,expr) +def destos_to_binfmt(key): + if key=='darwin': + return'mac-o' + elif key in('win32','cygwin','uwin','msys'): + return'pe' + return'elf' +def unversioned_sys_platform(): + s=sys.platform + if s.startswith('java'): + from java.lang import System + s=System.getProperty('os.name') + if s=='Mac OS X': + return'darwin' + elif s.startswith('Windows '): + return'win32' + elif s=='OS/2': + return'os2' + elif s=='HP-UX': + return'hp-ux' + elif s in('SunOS','Solaris'): + return'sunos' + else:s=s.lower() + if s=='powerpc': + return'darwin' + if s=='win32'or s=='os2': + return s + if s=='cli'and os.name=='nt': + return'win32' + return re.split('\d+$',s)[0] +def nada(*k,**kw): + pass +class Timer(object): + def __init__(self): + self.start_time=self.now() + def __str__(self): + delta=self.now()-self.start_time + if not isinstance(delta,datetime.timedelta): + delta=datetime.timedelta(seconds=delta) + days=delta.days + hours,rem=divmod(delta.seconds,3600) + minutes,seconds=divmod(rem,60) + seconds+=delta.microseconds*1e-6 + result='' + if days: + result+='%dd'%days + if days or hours: + result+='%dh'%hours + if days or hours or minutes: + result+='%dm'%minutes + return'%s%.3fs'%(result,seconds) + def now(self): + return datetime.datetime.utcnow() + if hasattr(time,'perf_counter'): + def now(self): + return time.perf_counter() +def read_la_file(path): + sp=re.compile(r'^([^=]+)=\'(.*)\'$') + dc={} + for line in readf(path).splitlines(): + try: + _,left,right,_=sp.split(line.strip()) + dc[left]=right + except ValueError: + pass + return dc +def run_once(fun): + cache={} + def wrap(*k): + try: + return cache[k] + except KeyError: + ret=fun(*k) + cache[k]=ret + return ret + wrap.__cache__=cache + wrap.__name__=fun.__name__ + return wrap +def get_registry_app_path(key,filename): + if not winreg: + return None + try: + result=winreg.QueryValue(key,"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s.exe"%filename[0]) + except OSError: + pass + else: + if os.path.isfile(result): + return result +def lib64(): + if os.sep=='/': + if platform.architecture()[0]=='64bit': + if os.path.exists('/usr/lib64')and not os.path.exists('/usr/lib32'): + return'64' + return'' +def sane_path(p): + return os.path.abspath(os.path.expanduser(p)) +process_pool=[] +def get_process(): + try: + return process_pool.pop() + except IndexError: + filepath=os.path.dirname(os.path.abspath(__file__))+os.sep+'processor.py' + cmd=[sys.executable,'-c',readf(filepath)] + return subprocess.Popen(cmd,stdout=subprocess.PIPE,stdin=subprocess.PIPE,bufsize=0) +def run_prefork_process(cmd,kwargs,cargs): + if not'env'in kwargs: + kwargs['env']=dict(os.environ) + try: + obj=base64.b64encode(cPickle.dumps([cmd,kwargs,cargs])) + except(TypeError,AttributeError): + return run_regular_process(cmd,kwargs,cargs) + proc=get_process() + if not proc: + return run_regular_process(cmd,kwargs,cargs) + proc.stdin.write(obj) + proc.stdin.write('\n'.encode()) + proc.stdin.flush() + obj=proc.stdout.readline() + if not obj: + raise OSError('Preforked sub-process %r died'%proc.pid) + process_pool.append(proc) + lst=cPickle.loads(base64.b64decode(obj)) + assert len(lst)==5 + ret,out,err,ex,trace=lst + if ex: + if ex=='OSError': + raise OSError(trace) + elif ex=='ValueError': + raise ValueError(trace) + elif ex=='TimeoutExpired': + exc=TimeoutExpired(cmd,timeout=cargs['timeout'],output=out) + exc.stderr=err + raise exc + else: + raise Exception(trace) + return ret,out,err +def lchown(path,user=-1,group=-1): + if isinstance(user,str): + import pwd + entry=pwd.getpwnam(user) + if not entry: + raise OSError('Unknown user %r'%user) + user=entry[2] + if isinstance(group,str): + import grp + entry=grp.getgrnam(group) + if not entry: + raise OSError('Unknown group %r'%group) + group=entry[2] + return os.lchown(path,user,group) +def run_regular_process(cmd,kwargs,cargs={}): + proc=subprocess.Popen(cmd,**kwargs) + if kwargs.get('stdout')or kwargs.get('stderr'): + try: + out,err=proc.communicate(**cargs) + except TimeoutExpired: + if kwargs.get('start_new_session')and hasattr(os,'killpg'): + os.killpg(proc.pid,signal.SIGKILL) + else: + proc.kill() + out,err=proc.communicate() + exc=TimeoutExpired(proc.args,timeout=cargs['timeout'],output=out) + exc.stderr=err + raise exc + status=proc.returncode + else: + out,err=(None,None) + try: + status=proc.wait(**cargs) + except TimeoutExpired as e: + if kwargs.get('start_new_session')and hasattr(os,'killpg'): + os.killpg(proc.pid,signal.SIGKILL) + else: + proc.kill() + proc.wait() + raise e + return status,out,err +def run_process(cmd,kwargs,cargs={}): + if kwargs.get('stdout')and kwargs.get('stderr'): + return run_prefork_process(cmd,kwargs,cargs) + else: + return run_regular_process(cmd,kwargs,cargs) +def alloc_process_pool(n,force=False): + global run_process,get_process,alloc_process_pool + if not force: + n=max(n-len(process_pool),0) + try: + lst=[get_process()for x in range(n)] + except OSError: + run_process=run_regular_process + get_process=alloc_process_pool=nada + else: + for x in lst: + process_pool.append(x) +def atexit_pool(): + for k in process_pool: + try: + os.kill(k.pid,9) + except OSError: + pass + else: + k.wait() +if(sys.hexversion<0x207000f and not is_win32)or sys.hexversion>=0x306000f: + atexit.register(atexit_pool) +if os.environ.get('WAF_NO_PREFORK')or sys.platform=='cli'or not sys.executable: + run_process=run_regular_process + get_process=alloc_process_pool=nada |