1import asyncio 2import os 3import sys 4import pstats 5import inspect 6import cProfile 7import ssl 8import tempfile 9from timeit import default_timer 10from urllib.error import HTTPError, URLError 11from urllib.request import urlopen 12 13from pychess import MSYS2 14 15# TODO: this hack only needed until we can figure out 16# what ssl cert files needed to copied in setup.py 17# when cx_freezee bdist_msi command is used 18if MSYS2: 19 ssl._create_default_https_context = ssl._create_unverified_context 20 21 22@asyncio.coroutine 23def download_file_async(url, progressbar=None): 24 loop = asyncio.get_event_loop() 25 future = loop.run_in_executor(None, download_file, url) 26 temp_file = yield from future 27 return temp_file 28 29 30def download_file(url, progressbar=None): 31 temp_file = None 32 try: 33 if progressbar is not None: 34 from gi.repository import GLib 35 GLib.idle_add(progressbar.set_text, "Downloading %s ..." % url) 36 else: 37 print("Downloading %s ..." % url) 38 f = urlopen(url) 39 40 temp_file = os.path.join(tempfile.gettempdir(), os.path.basename(url)) 41 with open(temp_file, "wb") as local_file: 42 local_file.write(f.read()) 43 44 except HTTPError as e: 45 print("HTTP Error:", e.code, url) 46 47 except URLError as e: 48 print("URL Error:", e.reason, url) 49 50 return temp_file 51 52 53def fident(f): 54 ''' 55 Get an identifier for a function or method 56 ''' 57 joinchar = '.' 58 if hasattr(f, 'im_class'): 59 fparent = f.im_class.__name__ 60 else: 61 joinchar = ':' 62 fparent = f.__module__.split('.')[-1] 63 64 # sometimes inspect.getsourcelines() segfaults on windows 65 if getattr(sys, 'frozen', False) or sys.platform == "win32": 66 lineno = 0 67 else: 68 lineno = inspect.getsourcelines(f)[1] 69 70 fullname = joinchar.join((fparent, f.__name__)) 71 return ':'.join((fullname, str(lineno))) 72 73 74def get_threadname(thread_namer): 75 if isinstance(thread_namer, str): 76 return thread_namer 77 else: 78 return fident(thread_namer) 79 80 81# https://gist.github.com/techtonik/2151727 82def caller_name(skip=2): 83 """Get a name of a caller in the format module.class.method 84 85 `skip` specifies how many levels of stack to skip while getting caller 86 name. skip=1 means "who calls me", skip=2 "who calls my caller" etc. 87 88 An empty string is returned if skipped levels exceed stack height 89 """ 90 stack = inspect.stack() 91 start = 0 + skip 92 if len(stack) < start + 1: 93 return '' 94 parentframe = stack[start][0] 95 96 name = [] 97 module = inspect.getmodule(parentframe) 98 # `modname` can be None when frame is executed directly in console 99 # TODO(techtonik): consider using __main__ 100 if module: 101 name.append(module.__name__) 102 # detect classname 103 if 'self' in parentframe.f_locals: 104 # I don't know any way to detect call from the object method 105 # XXX: there seems to be no way to detect static method call - it will 106 # be just a function call 107 name.append(parentframe.f_locals['self'].__class__.__name__) 108 codename = parentframe.f_code.co_name 109 if codename != '<module>': # top level usually 110 name.append(codename) # function or a method 111 del parentframe 112 return ".".join(name) 113 114 115def profile_me(fn): 116 def profiled_fn(*args, **kwargs): 117 prof = cProfile.Profile() 118 ret = prof.runcall(fn, *args, **kwargs) 119 ps = pstats.Stats(prof) 120 ps.sort_stats('cumulative') 121 ps.print_stats(60) 122 return ret 123 return profiled_fn 124 125 126# Python Timer Class - Context Manager for Timing Code Blocks 127# Corey Goldberg - 2012 128class Timer: 129 def __init__(self, text): 130 self.text = text 131 self.timer = default_timer 132 133 def __enter__(self): 134 self.start = self.timer() 135 return self 136 137 def __exit__(self, *args): 138 end = self.timer() 139 self.elapsed_secs = end - self.start 140 self.elapsed = self.elapsed_secs * 1000 # millisecs 141 print('---- elapsed time: %f ms - %s' % (self.elapsed, self.text)) 142