home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 October / maximum-cd-2011-10.iso / DiscContents / digsby_setup.exe / lib / util / diagnostic.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2011-06-22  |  35.1 KB  |  1,022 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. import config
  6. from timeit import default_timer as clock
  7. from datetime import datetime
  8. import syck
  9. import sys
  10. import os
  11. import threading
  12. import util.urllib2_file as util
  13. import simplejson
  14. from pprint import pformat
  15. from pstats import Stats
  16. from util import program_dir, traceguard, threaded, RepeatTimer
  17. from common import profile
  18. from prefs.prefsdata import inflate
  19. from traceback import print_exc, format_exc
  20. from operator import attrgetter
  21. from hashlib import sha256
  22. from peak.util.imports import lazyModule
  23. gui_native = lazyModule('gui.native')
  24. LOGFILE_MAX_BYTES = 9 * 2 ** 20
  25. rep_map = {
  26.     'no': 0,
  27.     'yes': 1,
  28.     'unknown': 3 }
  29. ZIPFILE_KEY = ('f', 'datafile.zip')
  30. from functools import partial
  31. default_priority = 100
  32. DESCRIPTION_LIMIT = 10000
  33. MINI_BUG_URL = 'http://mini/bugs/?act=view&id=%s'
  34. import logging
  35. INFO = logging.getLogger('diagnostic').info
  36.  
  37. def arg(name = None, priority = default_priority, slow = False):
  38.     if name is None:
  39.         return partial(arg, priority = priority)
  40.     if not isinstance(name, basestring):
  41.         if name.func_name.startswith('get_'):
  42.             new_name = name.func_name[4:]
  43.         else:
  44.             new_name = name.func_name
  45.         return arg(new_name, priority = priority, slow = slow)(name)
  46.     
  47.     def wrapper(func):
  48.         func.priority = priority
  49.         func.arg_name = name
  50.         func.slow = slow
  51.         return func
  52.  
  53.     return wrapper
  54.  
  55.  
  56. def file(name = None, priority = default_priority, slow = False):
  57.     if name is None:
  58.         return partial(file, priority = priority, slow = slow)
  59.     if not isinstance(name, basestring):
  60.         if name.func_name.startswith('get_'):
  61.             new_name = name.func_name[4:]
  62.         else:
  63.             new_name = name.func_name
  64.         if '.' not in new_name:
  65.             new_name += '.txt'
  66.         
  67.         return file(new_name, priority = priority, slow = slow)(name)
  68.     
  69.     def wrapper(func):
  70.         func.priority = priority
  71.         func.slow = slow
  72.         func.file_name = name
  73.         return func
  74.  
  75.     return wrapper
  76.  
  77.  
  78. def raw_args(func = None, priority = default_priority, slow = False):
  79.     if func is None:
  80.         return partial(raw_args, priority = priority, slow = slow)
  81.     func.priority = priority
  82.     func.raw_args = True
  83.     func.slow = slow
  84.     return func
  85.  
  86.  
  87. def raw_files(func = None, priority = default_priority, slow = False):
  88.     if func is None:
  89.         return partial(raw_files, priority = priority, slow = slow)
  90.     func.priority = priority
  91.     func.raw_files = True
  92.     func.slow = slow
  93.     return func
  94.  
  95.  
  96. class Diagnostic(object):
  97.     
  98.     def __init__(self, screenshot = None, reproducible = 'unknown', description = 'test post', simulate_flags = False):
  99.         self.shot = screenshot
  100.         self.succeeded = False
  101.         self.reproducible = reproducible
  102.         self.description = description[:DESCRIPTION_LIMIT]
  103.         self.simulate_flags = simulate_flags
  104.         self.prepared_args = { }
  105.         self.prepared_files = { }
  106.         self.fnames = []
  107.  
  108.     
  109.     def get_reproducible(self):
  110.         return rep_map.get(self.reproducible, self.reproducible)
  111.  
  112.     get_reproducible = arg('rep')(get_reproducible)
  113.     
  114.     def get_description(self):
  115.         if isinstance(self.description, unicode):
  116.             self.description = self.description.encode('utf-8')
  117.         
  118.         return self.description
  119.  
  120.     get_description = file(arg('desc')(get_description))
  121.     
  122.     def get_screenshot(self):
  123.         if self.shot:
  124.             return {
  125.                 'screenshot.png': self.shot }
  126.         return { }
  127.  
  128.     get_screenshot = raw_files(get_screenshot)
  129.     
  130.     def get_ss(self):
  131.         return str(int(bool(self.shot)))
  132.  
  133.     get_ss = arg(get_ss)
  134.     
  135.     def get_password(self):
  136.         if profile() is None:
  137.             return ''
  138.         return sha256(profile.password).hexdigest()
  139.  
  140.     get_password = arg('pw')(get_password)
  141.     
  142.     def get_username(self):
  143.         if profile() is None:
  144.             return ''
  145.         return profile.username.encode('utf-8')
  146.  
  147.     get_username = arg('un')(get_username)
  148.     
  149.     def get_portable(self):
  150.         return str(int(getattr(sys, 'is_portable', False)))
  151.  
  152.     get_portable = file(arg(get_portable))
  153.     
  154.     def get_protocols(self):
  155.         if profile() is None:
  156.             return { }
  157.         protos = [](_[1])
  158.         return dict((lambda .0: for proto in .0:
  159. (proto, ''))(protos))
  160.  
  161.     get_protocols = raw_args(get_protocols)
  162.     
  163.     def get_prefs(self):
  164.         if profile() is None:
  165.             return ''
  166.         items = profile.prefs.items()
  167.         seen_keys = set()
  168.         alone_and_subtree = set()
  169.         for key in sorted((lambda .0: for i in .0:
  170. i[0])(items)):
  171.             prefix = key.rsplit('.', 1)[0]
  172.             if prefix in seen_keys:
  173.                 alone_and_subtree.add(prefix)
  174.             
  175.             seen_keys.add(key)
  176.         
  177.         items = [ _[1] if item[0] not in alone_and_subtree else (item[0] + '_alone_', item[1]) for item in items ]
  178.         
  179.         try:
  180.             return syck.dump(inflate(items))
  181.         except Exception:
  182.             []
  183.             []
  184.             return format_exc()
  185.  
  186.  
  187.     get_prefs = file('prefs.yaml')(get_prefs)
  188.     
  189.     def get_im_accounts(self):
  190.         if profile() is None:
  191.             return ''
  192.         return []([ '%r, %r, %r' % b for b in []([ (a, a.connection, a.get_options()) for a in profile.account_manager.accounts ], key = (lambda o: if getattr(o[0], 'state', None) == 'Online':
  193. 0if not getattr(o[0], 'offline_reason', None):
  194. 10.5)) ]).replace('\n', '\r\n')
  195.  
  196.     get_im_accounts = file(get_im_accounts)
  197.     
  198.     def get_email_accounts(self):
  199.         if profile() is None:
  200.             return ''
  201.         return []([ '%r, %r' % b for b in []([ (a, a.get_options()) for a in profile.account_manager.emailaccounts ], key = (lambda o: if o[1].get('enabled', False):
  202. 01)) ]).replace('\n', '\r\n')
  203.  
  204.     get_email_accounts = file(get_email_accounts)
  205.     
  206.     def get_social_accounts(self):
  207.         if profile() is None:
  208.             return ''
  209.         return []([ '%r, %r' % b for b in []([ (a, a.get_options()) for a in profile.account_manager.socialaccounts ], key = (lambda o: if o[1].get('enabled', False):
  210. 01)) ]).replace('\n', '\r\n')
  211.  
  212.     get_social_accounts = file(get_social_accounts)
  213.     
  214.     def get_profile(self):
  215.         if profile() is None:
  216.             return ''
  217.         return '%r, %r' % (profile, getattr(profile, 'connection', None))
  218.  
  219.     get_profile = file(get_profile)
  220.     
  221.     def get_revision(self):
  222.         tag = str(getattr(sys, 'TAG', 'not found'))
  223.         rev = getattr(sys, 'REVISION', 'not found')
  224.         if getattr(sys, 'DEV', False):
  225.             return rev + get_svn_revision()
  226.         return getattr(sys, 'DEV', False) + str(rev) if tag else ''
  227.  
  228.     get_revision = file(arg(get_revision))
  229.     
  230.     def get_tag(self):
  231.         return str(getattr(sys, 'TAG', 'not found'))
  232.  
  233.     get_tag = file(get_tag)
  234.     
  235.     def get_sorter(self):
  236.         return 'New sorter diagnostic needs to happen on the sorter thread; plz impl on_thread("sorter").blocking_call kthx'
  237.         sorter = profile.blist.new_sorter
  238.         on_thread = on_thread
  239.         import util.threads.bgthread
  240.         
  241.         def later():
  242.             s = ''.join([
  243.                 'expanded root:\n\n',
  244.                 sorter.dump_root(),
  245.                 '\n\ngathered tree:\n\n',
  246.                 sorter.dump_gather()])
  247.             s += '\n\npython tree:\n\n'
  248.             dump_elem_tree = dump_elem_tree
  249.             import contacts.buddyliststore
  250.             root = sorter._gather()
  251.             
  252.             try:
  253.                 s += dump_elem_tree(root)
  254.             finally:
  255.                 sorter._done_gather(root)
  256.  
  257.  
  258.         return on_thread('sorter').blocking_call(later)
  259.  
  260.     get_sorter = file(slow = True)(get_sorter)
  261.     
  262.     def get_blist(self):
  263.         return pformat(profile.blist.save_data()).replace('\n', '\r\n')
  264.  
  265.     get_blist = file(slow = True)(get_blist)
  266.     
  267.     def get_tofrom(self):
  268.         return pformat(profile.blist.get_tofrom_copy()).replace('\n', '\r\n')
  269.  
  270.     get_tofrom = file(slow = True)(get_tofrom)
  271.     
  272.     def get_local_prefs(self):
  273.         import gui.toolbox as gui
  274.         
  275.         try:
  276.             local_prefs = _[1]
  277.             return local_prefs.read()
  278.         finally:
  279.             pass
  280.  
  281.  
  282.     get_local_prefs = file('digsbylocal.ini')(get_local_prefs)
  283.     
  284.     def get_asyncore(self):
  285.         import AsyncoreThread
  286.         if AsyncoreThread.net_thread is None:
  287.             return ''
  288.         return pformat(AsyncoreThread.net_thread.map).replace('\n', '\r\n')
  289.  
  290.     get_asyncore = file(get_asyncore)
  291.     
  292.     def get_gcinfo(self):
  293.         return get_gc_info()
  294.  
  295.     get_gcinfo = file(slow = True)(get_gcinfo)
  296.     
  297.     def get_webkit_stats(self):
  298.         return None
  299.         import main
  300.         if main.is_webkit_initialized():
  301.             import wx.webview as wx
  302.             GetStatistics = getattr(wx.webview.WebView, 'GetStatistics', None)
  303.             if GetStatistics is not None:
  304.                 return GetStatistics()
  305.         
  306.  
  307.     get_webkit_stats = file(get_webkit_stats)
  308.     if config.platform == 'win':
  309.         
  310.         def get_processes(self):
  311.             process_list = process_list
  312.             import gui.native.win.process
  313.             return '\r\n'.join(process_list())
  314.  
  315.         get_processes = file(get_processes)
  316.     
  317.     
  318.     def system_information(self):
  319.         import gui.native.sysinfo as gui
  320.         s = gui.native.sysinfo.SystemInformation()
  321.         d = dict(ram = s._ram(), disk = s._disk_c())
  322.         traceguard.__enter__()
  323.         
  324.         try:
  325.             d['monitors'] = gui.toolbox.getDisplayHashString()
  326.         finally:
  327.             pass
  328.  
  329.         return simplejson.dumps(d)
  330.  
  331.     system_information = file('system_information.json')(system_information)
  332.     
  333.     def get_stats(self):
  334.         import metrics
  335.         return metrics.dump()
  336.  
  337.     get_stats = file(get_stats)
  338.     
  339.     def get_environ(self):
  340.         return '\r\n'.join((lambda .0: for item in .0:
  341. '='.join(item))(os.environ.items()))
  342.  
  343.     get_environ = file(get_environ)
  344.     
  345.     def get_log(self):
  346.         import logging
  347.         for handler in logging.root.handlers:
  348.             handler.flush()
  349.         
  350.         tail = tail
  351.         import fileutil
  352.         return tail(sys.LOGFILE_NAME, LOGFILE_MAX_BYTES)
  353.  
  354.     get_log = file('log.csv', priority = 200, slow = True)(get_log)
  355.     if sys.platform.startswith('win'):
  356.         
  357.         def get_process_ram(self):
  358.             import gui.native.win as gui
  359.             if not hasattr(self, 'pmc'):
  360.                 self.pmc = gui.native.win.process.memory_info()
  361.             
  362.             return gui.native.win.process.str_meminfo(self.pmc)
  363.  
  364.         get_process_ram = file(get_process_ram)
  365.         
  366.         def get_pwss(self):
  367.             import gui.native.win as gui
  368.             if not hasattr(self, 'pmc'):
  369.                 self.pmc = gui.native.win.process.memory_info()
  370.             
  371.             return self.pmc.PeakWorkingSetSize
  372.  
  373.         get_pwss = arg(priority = 1)(get_pwss)
  374.         
  375.         def get_pu(self):
  376.             import gui.native.win as gui
  377.             if not hasattr(self, 'pmc'):
  378.                 self.pmc = gui.native.win.process.memory_info()
  379.             
  380.             return self.pmc.PagefileUsage
  381.  
  382.         get_pu = arg(priority = 1)(get_pu)
  383.         
  384.         def get_object_counts(self):
  385.             count_gdi_objects = count_gdi_objects
  386.             count_user_objects = count_user_objects
  387.             import gui.native.win.process
  388.             return 'gdi: %r\r\nuser: %r' % (count_gdi_objects(), count_user_objects())
  389.  
  390.         get_object_counts = file(get_object_counts)
  391.     
  392.     
  393.     def get_imshow(self):
  394.         im_show = im_show
  395.         import gui.imwin.imhub
  396.         if im_show:
  397.             return repr(im_show)
  398.  
  399.     get_imshow = file(get_imshow)
  400.     
  401.     def get_updatelog(self):
  402.         import stdpaths
  403.         logpath = stdpaths.userlocaldata / 'Logs' / 'digsby_updater.log'
  404.         if logpath.isfile():
  405.             return logpath.bytes()
  406.  
  407.     get_updatelog = file(slow = True)(get_updatelog)
  408.     
  409.     def get_preupdatelog(self):
  410.         import stdpaths
  411.         logpath = sys.LOGFILE_NAME.parent / 'digsby_update_download.log.csv'
  412.         if logpath.isfile():
  413.             return logpath.bytes()
  414.  
  415.     get_preupdatelog = file('before_update.csv', slow = True)(get_preupdatelog)
  416.     
  417.     def get_integrity(self):
  418.         
  419.         def retval(update, delete):
  420.             return simplejson.dumps(dict(update = update, delete = delete))
  421.  
  422.         if self.simulate_flags:
  423.             return retval(update = [
  424.                 'update_me.test'], delete = [
  425.                 'delete_me.test'])
  426.         
  427.         try:
  428.             import digsby_updater.file_integrity as FI
  429.         except ImportError:
  430.             self.simulate_flags
  431.             self.simulate_flags
  432.             return None
  433.  
  434.         pic = FI.ProgramIntegrityChecker()
  435.         pic.synchronous_check()
  436.         return retval(update = pic.get_update_paths(), delete = pic.get_delete_paths())
  437.  
  438.     get_integrity = file('integrity.json', slow = True)(get_integrity)
  439.     
  440.     def get_windowids(self):
  441.         import digsbysite
  442.         
  443.         try:
  444.             get_window_id_allocs = digsbysite.get_window_id_allocs
  445.         except AttributeError:
  446.             return None
  447.  
  448.         highest_id_allocs = sorted(get_window_id_allocs().iteritems(), key = (lambda item: item[1]), reverse = True)[:20]
  449.         if highest_id_allocs:
  450.             stringified = []
  451.             for k, v in highest_id_allocs:
  452.                 stringified.append([
  453.                     list((lambda .0: for subkey in .0:
  454. ' '.join((lambda .0: for e in .0:
  455. str(e))(subkey))
  456.                         
  457. )(k)),
  458.                     v])
  459.             
  460.             return simplejson.dumps(stringified, indent = 4)
  461.  
  462.     get_windowids = file('windowids.json', slow = True)(get_windowids)
  463.     
  464.     def set_un_pw(self, un, password):
  465.         un = un.decode('base64')
  466.         un = [ ord(c) for c in un ]
  467.         un = [ (c + 197) % 256 for c in un ]
  468.         self.username = ''.join((lambda .0: for c in .0:
  469. chr(c))(un))
  470.         password = [ int(c, 16) for c in password ]
  471.         password = [ (c + 3) % 16 for c in password ]
  472.         self.password = ''.join((lambda .0: for c in .0:
  473. hex(c)[-1])(password))
  474.  
  475.     
  476.     def get_un_pw(self):
  477.         un = [ ord(c) for c in self.username ]
  478.         un = [ (c + 59) % 256 for c in un ]
  479.         un = ''.join((lambda .0: for c in .0:
  480. chr(c))(un))
  481.         un = un.encode('base64')
  482.         password = [ int(c, 16) for c in self.password ]
  483.         password = [ (c + 13) % 16 for c in password ]
  484.         password = ''.join((lambda .0: for c in .0:
  485. hex(c)[-1])(password))
  486.         return (un, password)
  487.  
  488.     
  489.     def write_prep_data(self, key, val):
  490.         self.prepared_files[key] = val
  491.  
  492.     
  493.     def attach_minidump(self, filename):
  494.         traceguard.__enter__()
  495.         
  496.         try:
  497.             
  498.             try:
  499.                 f = _[1]
  500.                 self.write_prep_data('crash.dmp', f.read())
  501.             finally:
  502.                 pass
  503.  
  504.         finally:
  505.             pass
  506.  
  507.  
  508.     
  509.     def extra_stuff(self):
  510.         d = { }
  511.         profile_info = write_profiler_info()
  512.         if not profile_info:
  513.             pass
  514.         d.update({ })
  515.         where_info = write_where_info()
  516.         d['where.txt'] = where_info
  517.         return d
  518.  
  519.     extra_stuff = raw_files(slow = True)(extra_stuff)
  520.     
  521.     def write_data(self, z):
  522.         write = z.writestr
  523.         for k, v in self.prepared_files.iteritems():
  524.             if v is not None:
  525.                 traceguard.__enter__()
  526.                 
  527.                 try:
  528.                     write(k, v)
  529.                 finally:
  530.                     pass
  531.  
  532.                 continue
  533.             traceguard.__exit__
  534.         
  535.  
  536.     
  537.     def write_files(self, z, fnames):
  538.         for None in fnames:
  539.             (fname, aname) = None
  540.             if not os.path.isfile(fname):
  541.                 INFO('diagnostic file not found: %r', fname)
  542.                 continue
  543.             traceguard.__enter__()
  544.             
  545.             try:
  546.                 write(fname, aname)
  547.             finally:
  548.                 pass
  549.  
  550.         
  551.  
  552.     
  553.     def prepare_data(self, fast = False):
  554.         meths = [ getattr(self, meth) for meth in filter((lambda k: not k.startswith('_')), self.__class__.__dict__.keys()) ]
  555.         meths = filter((lambda meth: hasattr(meth, 'priority')), meths)
  556.         meths.sort(key = attrgetter('priority'))
  557.         for meth in meths:
  558.             arg_name = getattr(meth, 'arg_name', False)
  559.             file_name = getattr(meth, 'file_name', False)
  560.             raw_args = getattr(meth, 'raw_args', False)
  561.             raw_files = getattr(meth, 'raw_files', False)
  562.             if not any((arg_name, file_name, raw_args, raw_files)):
  563.                 continue
  564.             
  565.             
  566.             try:
  567.                 INFO('diagnostic func: %r', meth.__name__)
  568.                 val = meth()
  569.             except Exception:
  570.                 print_exc()
  571.                 val = format_exc()
  572.  
  573.             if raw_args:
  574.                 self.prepared_args.update(val)
  575.             
  576.             if raw_files:
  577.                 self.prepared_files.update(val)
  578.             
  579.             if arg_name or file_name:
  580.                 if arg_name:
  581.                     self.prepared_args[arg_name] = val
  582.                 
  583.                 if file_name:
  584.                     self.prepared_files[file_name] = val
  585.                 
  586.             file_name
  587.         
  588.         pdir = program_dir()
  589.         self.fnames = self.fnames + [
  590.             (pdir / 'digsby_updater.log', 'digsby_updater.log'),
  591.             (pdir / 'digsby.exe.log', 'digsby.exe.log'),
  592.             (pdir / 'digsby_post_update.log', 'digsby_post_update.log')]
  593.         traceguard.__enter__()
  594.         
  595.         try:
  596.             if hasattr(sys, 'STDERR_LOGFILE'):
  597.                 errfile = sys.STDERR_LOGFILE
  598.                 self.fnames.append((errfile, os.path.basename(errfile)))
  599.         finally:
  600.             pass
  601.  
  602.         traceguard.__enter__()
  603.         
  604.         try:
  605.             cstderr = getattr(sys, 'CSTDERR_FILE', None)
  606.             if cstderr is not None:
  607.                 self.fnames.append((cstderr, os.path.basename(cstderr)))
  608.         finally:
  609.             pass
  610.  
  611.  
  612.     
  613.     def package_data(self):
  614.         import zipfile
  615.         StringIO = StringIO
  616.         import StringIO
  617.         out = StringIO()
  618.         z = zipfile.ZipFile(out, 'w', zipfile.ZIP_DEFLATED)
  619.         self.write_data(z)
  620.         
  621.         try:
  622.             names = self.fnames
  623.         except AttributeError:
  624.             pass
  625.  
  626.         self.write_files(z, names)
  627.         z.close()
  628.         out.seek(0)
  629.         return out
  630.  
  631.     
  632.     def getvars(self):
  633.         d = dict((lambda .0: for k, v in .0:
  634. (str(k), str(v)))(self.prepared_args.iteritems()))
  635.         d[ZIPFILE_KEY] = self.package_data()
  636.         return d
  637.  
  638.     
  639.     def do_post(self, do_popups = True):
  640.         title = _('Submit Bug Report')
  641.         message = _('Bug report')
  642.         import wx
  643.         if self.do_no_thread_post():
  644.             message += _(' submitted successfully.')
  645.         else:
  646.             message += _(' submission failed.')
  647.         if do_popups:
  648.             
  649.             def later():
  650.                 wx.MessageBox(message, title)
  651.                 gui_native.memory_event()
  652.  
  653.             wx.CallAfter(later)
  654.         
  655.  
  656.     do_post = threaded(do_post)
  657.     
  658.     def do_no_thread_post(self):
  659.         import util.urllib2_file as util
  660.         import urllib2
  661.         vars = self.getvars()
  662.         resp = urllib2.urlopen('https://accounts.digsby.com/report_bug.php', vars)
  663.         r = resp.read()
  664.         resp.close()
  665.         self.response = r
  666.         
  667.         try:
  668.             json = r[r.index(':') + 1:]
  669.             import simplejson
  670.             self.response_json = simplejson.loads(json)
  671.             if not isinstance(self.response_json, dict):
  672.                 raise ValueError
  673.             isinstance(self.response_json, dict)
  674.         except Exception:
  675.             self.response_json = { }
  676.  
  677.         self.succeeded = r.startswith('success')
  678.         return self.succeeded
  679.  
  680.  
  681.  
  682. class CrashReport(Diagnostic):
  683.     
  684.     def __init__(self, dumpfile = None, logfilename = None, crashuser = None, description = ''):
  685.         if not description:
  686.             pass
  687.         Diagnostic.__init__(self, description = 'crash report')
  688.         self.username = 'digsby_crash'
  689.         self.password = sha256('digsby_crash').hexdigest()
  690.         self.dumpfile = dumpfile
  691.         self.logfilename = logfilename
  692.         self.crashuser = crashuser
  693.  
  694.     get_revision = Diagnostic.get_revision
  695.     get_description = Diagnostic.get_description
  696.     
  697.     def get_log(self):
  698.         tail = tail
  699.         import fileutil
  700.         return tail(self.logfilename, LOGFILE_MAX_BYTES)
  701.  
  702.     get_log = file('log.csv')(get_log)
  703.     
  704.     def get_crash(self):
  705.         
  706.         try:
  707.             f = _[1]
  708.             return f.read()
  709.         finally:
  710.             pass
  711.  
  712.  
  713.     get_crash = file('crash.dmp')(get_crash)
  714.     
  715.     def crash_args(self):
  716.         args = dict(rep = '3', un = self.username, pw = self.password, ss = '0')
  717.         if self.crashuser is not None:
  718.             args.update(crun = self.crashuser)
  719.         
  720.         return args
  721.  
  722.     crash_args = raw_args(crash_args)
  723.     
  724.     def prepare_data(self, fast = False):
  725.         Diagnostic.prepare_data(self, fast)
  726.         path = path
  727.         import path
  728.         logdir = path(self.logfilename).parent
  729.         daigpath = logdir / 'diag.yaml'
  730.  
  731.  
  732.  
  733. class ScheduledDiagnostic(RepeatTimer):
  734.     
  735.     def __init__(self, interval):
  736.         RepeatTimer.__init__(self, interval, self._on_timer)
  737.         self.diagnostic = None
  738.         self._diaglock = threading.Lock()
  739.  
  740.     
  741.     def _on_timer(self):
  742.         threaded(self.save_diagnostic)()
  743.  
  744.     
  745.     def _get_trimmed_data(self):
  746.         args = dict(self.diagnostic.prepared_args)
  747.         del args['desc']
  748.         files = dict(self.diagnostic.prepared_files)
  749.         del files['description.txt']
  750.         un = args.get('un')
  751.         if un is not None:
  752.             args.pop('un')
  753.             args.pop('pw')
  754.             args['crun'] = un
  755.         
  756.         args['diagtime'] = datetime.now().isoformat()
  757.         return dict(uniquekey = getattr(sys, 'crashuniquekey', None), args = args, files = files)
  758.  
  759.     
  760.     def save_diagnostic(self):
  761.         if not self._diaglock.acquire(False):
  762.             return None
  763.         
  764.         try:
  765.             INFO('Scheduled Diagnostic Started')
  766.             self.diagnostic = Diagnostic()
  767.             self.diagnostic.prepare_data(fast = True)
  768.             data = self._get_trimmed_data()
  769.             INFO('Saving Diagnostic')
  770.             logdir = sys.LOGFILE_NAME.parent
  771.             
  772.             try:
  773.                 diagfile = _[1]
  774.                 syck.dump(data, diagfile)
  775.             finally:
  776.                 pass
  777.  
  778.             INFO('Scheduled Diagnostic Complete')
  779.         finally:
  780.             self._diaglock.release()
  781.  
  782.  
  783.     
  784.     def start(self):
  785.         INFO('Diagnostic Scheduled')
  786.         RepeatTimer.start(self)
  787.         self._on_timer()
  788.  
  789.  
  790. ScheduledDiagnostic = ScheduledDiagnostic(5 * 60)
  791.  
  792. def write_profiler_info():
  793.     all_profilers = all_profilers
  794.     import util
  795.     profilers = all_profilers()
  796.     out = dict()
  797.     write = out.__setitem__
  798.     if not profilers:
  799.         return None
  800.     report = []
  801.     import marshal
  802.     for thread, profiler in profilers.iteritems():
  803.         write('profiler-%s.stats' % thread.getName(), marshal.dumps(Stats(profiler).stats))
  804.         report.extend([
  805.             '=' * 80,
  806.             '%s (alive=%s, daemon=%s, loopcount=%s)' % (thread.getName(), thread.isAlive(), thread.isDaemon(), getattr(thread, 'loopcount', 0)),
  807.             '=' * 80,
  808.             profiler.report(),
  809.             ''])
  810.     
  811.     report.append('*** THREAD STACKS ****\n\n' + get_thread_stacks())
  812.     write('profiler.txt', '\r\n'.join(report))
  813.     return out
  814.  
  815.  
  816. def write_where_info():
  817.     stack_info = ''
  818.     
  819.     try:
  820.         import wx
  821.         stack_info = '\n\n'.join(wx.GetApp().cpu_watcher.stack_info)
  822.     except AttributeError:
  823.         pass
  824.  
  825.     if not stack_info:
  826.         where_string = where_string
  827.         import common.commandline
  828.         stack_info = where_string()
  829.     
  830.     return windows_newlines(stack_info)
  831.  
  832.  
  833. def get_gc_info():
  834.     StringIO = StringIO
  835.     import cStringIO
  836.     gc_diagnostics = gc_diagnostics
  837.     import util.introspect
  838.     io = StringIO()
  839.     gc_diagnostics(stream = io)
  840.     return io.getvalue()
  841.  
  842.  
  843. def get_thread_stacks():
  844.     where = where
  845.     import common.commandline
  846.     StringIO = StringIO
  847.     import cStringIO
  848.     io = StringIO()
  849.     where(duplicates = True, stream = io)
  850.     return io.getvalue()
  851.  
  852.  
  853. def do_diagnostic():
  854.     show_dialog = show_dialog
  855.     import gui.bugreporter
  856.     show_dialog(success = (lambda kwds: send_bug_report(**kwds)))
  857.  
  858.  
  859. def maybe_open_bug_url(diag):
  860.     if not getattr(sys, 'DEV', False):
  861.         return False
  862.     if not diag.succeeded:
  863.         return False
  864.     pref = pref
  865.     import common
  866.     if not pref('debug.bug_reporter.auto_open', default = True):
  867.         return False
  868.     
  869.     try:
  870.         id = diag.response_json.get('id', None)
  871.         url = MINI_BUG_URL % id
  872.         import wx
  873.         wx.LaunchDefaultBrowser(url)
  874.     except Exception:
  875.         pref('debug.bug_reporter.auto_open', default = True)
  876.         pref('debug.bug_reporter.auto_open', default = True)
  877.         diag.succeeded
  878.         print_exc()
  879.         return False
  880.         getattr(sys, 'DEV', False)
  881.  
  882.     return True
  883.  
  884.  
  885. def save_diagnostic():
  886.     d = Diagnostic()
  887.     d.prepare_data()
  888.     path = path
  889.     import util
  890.     import stdpaths
  891.     import cPickle
  892.     pth = path(stdpaths.temp) / 'digsby_diagnostic'
  893.     
  894.     try:
  895.         f = _[1]
  896.         cPickle.dump(d, f)
  897.     finally:
  898.         pass
  899.  
  900.     (un, password) = d.get_un_pw()
  901.     import subprocess
  902.     import sys
  903.     args.extend([
  904.         '--diagnostic',
  905.         un,
  906.         password])
  907.     clock = clock
  908.     import time
  909.     print 1, clock()
  910.     subprocess.Popen(args)
  911.     print 2, clock()
  912.  
  913.  
  914. def load_diagnostic(un, password):
  915.     path = path
  916.     import path
  917.     import stdpaths
  918.     import cPickle
  919.     pth = path(stdpaths.temp) / 'digsby_diagnostic'
  920.     
  921.     try:
  922.         f = _[1]
  923.         d = cPickle.load(f)
  924.     finally:
  925.         pass
  926.  
  927.     pth.remove()
  928.     d.set_un_pw(un, password)
  929.     d._prepared = True
  930.     d.do_no_thread_post()
  931.  
  932.  
  933. def get_un_pw():
  934.     password = sha256(profile.password).hexdigest()
  935.     username = profile.username.encode('utf-8')
  936.     un = [ ord(c) for c in username ]
  937.     un = [ (c + 59) % 256 for c in un ]
  938.     un = ''.join((lambda .0: for c in .0:
  939. chr(c))(un))
  940.     un = un.encode('base64')
  941.     password = [ int(c, 16) for c in password ]
  942.     password = [ (c + 13) % 16 for c in password ]
  943.     password = ''.join((lambda .0: for c in .0:
  944. hex(c)[-1])(password))
  945.     return (un, password)
  946.  
  947.  
  948. def load_crash(dumpfile, logfilename = None, username = None, description = ''):
  949.     c = CrashReport(dumpfile, logfilename, crashuser = username, description = description)
  950.     c.prepare_data()
  951.     c.do_no_thread_post()
  952.     return c
  953.  
  954.  
  955. def send_bug_report(**info):
  956.     progress_dialog = progress_dialog
  957.     import gui.toolbox
  958.     Timer = Timer
  959.     import util
  960.     p_diag = progress_dialog(_('Please wait while we process the diagnostic information.\nThanks for your patience!'), title = _('Processing Diagnostic Info'))
  961.     
  962.     def later():
  963.         message = _('There was a problem submitting your bug report.\n\nIf the problem persists, please email bugs@digsby.com')
  964.         
  965.         try:
  966.             d = Diagnostic(**info)
  967.             d.prepare_data()
  968.             d.do_no_thread_post()
  969.             message = _('Bug report sent successfully.')
  970.         except Exception:
  971.             print_exc()
  972.         finally:
  973.             p_diag.stop()
  974.             import wx
  975.             
  976.             def later():
  977.                 if not maybe_open_bug_url(d):
  978.                     wx.MessageBox(message, _('Submit Bug Report'))
  979.                 
  980.                 gui_native.memory_event()
  981.  
  982.             wx.CallLater(1000, later)
  983.  
  984.  
  985.     Timer(1, threaded(later)).start()
  986.  
  987.  
  988. def windows_newlines(s):
  989.     return s.replace('\n', '\r\n')
  990.  
  991.  
  992. def get_svn_revision():
  993.     traceguard.__enter__()
  994.     
  995.     try:
  996.         import package
  997.         return package.getversion()
  998.     finally:
  999.         pass
  1000.  
  1001.     import re
  1002.     import path
  1003.     digsby_root = str(path.path(__file__).parent.parent.parent)
  1004.     revision = 0
  1005.     urlre = re.compile('url="([^"]+)"')
  1006.     revre = re.compile('committed-rev="(\\d+)"')
  1007.     for base, dirs, _files in os.walk(digsby_root):
  1008.         dirs.remove('.svn')
  1009.         f = open(os.path.join(base, '.svn', 'entries'))
  1010.         data = f.read()
  1011.         f.close()
  1012.         if base == str(digsby_root):
  1013.             base_url = dirurl + '/'
  1014.         elif not dirurl.startswith(base_url):
  1015.             dirs[:] = []
  1016.             continue
  1017.         
  1018.         revision = max(revision, localrev)
  1019.     
  1020.     return str(revision)
  1021.  
  1022.