home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 February / maximum-cd-2011-02.iso / DiscContents / digsby_setup85.exe / lib / util / diagnostic.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-11-24  |  31.5 KB  |  924 lines

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