Advertisement
Mozai

hw_list_for_mom.py

Aug 25th, 2014
232
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.83 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. import re, subprocess
  4. import gtk
  5.  
  6. # Note: I've got two items where I use a 'fudge factor' on the numbers.
  7. #   My purpose is to make the numbers easier for my mother when
  8. #   she compares computer hardware.  Sometimes stores are off by 1.5% in
  9. #   how many inches a thing is, and it's better to give a guess for power
  10. #   consumption rather than "well it depends on many factors..."
  11.  
  12.  
  13. def getCPUs():
  14.   found = []
  15.   cpuinfo = open('/proc/cpuinfo')
  16.   cpunum = -1
  17.   for line in cpuinfo.readlines():
  18.     if '\t: ' not in line:
  19.       continue
  20.     key, val = re.split(r'\s+:\s+', line.strip(), 1)
  21.     if key == 'processor':
  22.       cpunum += 1
  23.       found.append({})
  24.     found[cpunum][key] = val
  25.   cpuinfo.close()
  26.   return found
  27.  
  28.  
  29. def prettyCPUs(found):
  30.   answer = ''
  31.   i = 0
  32.   while i < len(found):
  33.     answer += found[i]['model name']
  34.     if 'lm' in found[i]['flags']:
  35.       answer += ' (64-bit)'
  36.     if 'cpu cores' in found[i]:
  37.       j = int(found[i]['cpu cores'])
  38.       if j == 2:
  39.         answer += ' (dual-core)'
  40.       elif j == 4:
  41.         answer += ' (quad-core)'
  42.       else:
  43.         answer += ' (multi-core)'
  44.       i = i + j - 1
  45.     answer += "\n"
  46.     i += 1
  47.   while '  ' in answer:
  48.     answer = answer.replace('  ', ' ')
  49.   return answer.strip()
  50.  
  51.  
  52. def prettyDistro():
  53.   dist = subprocess.check_output(['lsb_release', '-ir']).strip()
  54.   dist = re.sub(r'(Distributor ID:\s+|Release:\s+)', '', dist).replace("\n", ' ')
  55.   return dist
  56.  
  57.  
  58. def prettyKernel():
  59.   kern = subprocess.check_output(['uname', '-srp']).strip()
  60.   kern = re.sub(r'i.86\b', '(32-bit)', kern)
  61.   kern = re.sub(r'x86_64', '(64-bit)', kern)
  62.   return kern
  63.  
  64.  
  65. def getDiskSizes():
  66.   res = subprocess.Popen(['df', '-BG', '-lPT'], stdout=subprocess.PIPE)
  67.   found = []
  68.   for line in res.stdout.readlines():
  69.     if not line.startswith('/'):
  70.       continue  # not a local device
  71.     dfi = line.split()
  72.     found.append({'name': dfi[0], 'type': dfi[1], 'total': int(dfi[2][:-1]),
  73.                   'inuse': int(dfi[3][:-1]), 'unused': int(dfi[4][:-1])})
  74.   res.stdout.close()
  75.   return found
  76.  
  77.  
  78. def prettyDiskSizes(found):
  79.   answer = ''
  80.   for part in found:
  81.     newtype = part['type']
  82.     if 'fat' in part['type'] or 'NTFS' == part['type']:
  83.       newtype = 'Windows'
  84.     if 'ext' in part['type']:
  85.       newtype = 'Linux'
  86.     warning = ''
  87.     if (part['unused'] * 100 / part['total']) < 18:
  88.       warning = '{low space}'
  89.     answer += "%s (%s) Size: %dGB Remains: %dGB %s\n" % (part['name'], newtype, part['total'], part['unused'], warning)
  90.   return answer.strip()
  91.  
  92.  
  93. def getMemInfo():
  94.   meminfo = open('/proc/meminfo')
  95.   found = {}
  96.   for line in meminfo.readlines():
  97.     if ': ' not in line:
  98.       continue
  99.     key, val = re.split(r'\s*:\s+', line.strip(), 1)
  100.     if val.endswith('kB'):
  101.       found[key] = int(val[:-3]) * 1024
  102.     elif val.endswith('MB'):
  103.       found[key] = int(val[:-3]) * 1024 * 1024
  104.     else:
  105.       found[key] = int(val)
  106.   meminfo.close()
  107.   return found
  108.  
  109.  
  110. def prettyMemInfo(found):
  111.   answer = 'installed memory '
  112.   meg = 1024 * 1024
  113.   gig = meg * 1024
  114.   if found['MemTotal'] > gig:
  115.     answer = '%.1f GB' % (found['MemTotal'] * 10 / gig / 10.0)
  116.   else:
  117.     answer = '%.1f MB' % (found['MemTotal'] * 10 / meg / 10.0)
  118.   if (found['SwapFree'] * 100 / found['SwapTotal']) < 50:
  119.     answer += ' {could use more}'
  120.   return answer
  121.  
  122.  
  123. def prettyVGAcard():
  124.   res = subprocess.Popen(['lspci', '-mm'], stdout=subprocess.PIPE)
  125.   answer = ''
  126.   for line in res.stdout.readlines():
  127.     found = re.search(r'"VGA compatible controller" "(.*?)" "(.*?)"', line)
  128.     if found is not None:
  129.       answer = found.group(1) + ' ' + found.group(2)
  130.       break
  131.   res.stdout.close()
  132.   return answer
  133.  
  134.  
  135. def prettyScreensize():
  136.   res = subprocess.Popen('xdpyinfo', stdout=subprocess.PIPE)
  137.   answer = ''
  138.   for line in res.stdout.readlines():
  139.     match = re.search(r'\s*dimensions:\s*(\d+)x(\d+)', line)
  140.     if match is not None:
  141.       w, h = int(match.group(1)), int(match.group(2))
  142.       answer = 'Desktop resolution: %dx%d' % (w, h)
  143.       if (w * 10 / h) == 16:
  144.         answer += " (16:9)"
  145.       elif (w * 100 / h) == 133:
  146.         answer += " (4:3)"
  147.       match = re.search(r'(\d+)x(\d+)\s+millimeters', line)
  148.       if match is not None:
  149.         w, h = float(match.group(1)), float(match.group(2))
  150.         diag = pow((pow(w, 2) + pow(h, 2)), 0.5)
  151.         diag /= 23.5
  152.         diag *= .91666  # fudge factor
  153.         answer += " {%.1f\" diagonal?}" % diag
  154.       break
  155.   res.stdout.close()
  156.   return answer.strip()
  157.  
  158.  
  159. def prettyScreenDiag():
  160.   answer = "Get a measuring tape, measure from the lower-left corner\n"
  161.   answer += "across to the upper-right corner, in inches ie. 15.7\" diagonal\n"
  162.   return answer.strip()
  163.  
  164.  
  165. def prettyBattery():
  166.   # this works on Ubuntu w/ GNOME, don't know about Kubuntu or Fedora or others
  167.   res = subprocess.Popen(['upower', '-e'], stdout=subprocess.PIPE)
  168.   bnames = []
  169.   for line in res.stdout.readlines():
  170.     if 'battery' in line:
  171.       bnames.append(line.strip())
  172.   res.stdout.close()
  173.   answer = ''
  174.   for batt in bnames:
  175.     battery = {}
  176.     res = subprocess.Popen(['upower', '-i', batt], stdout=subprocess.PIPE)
  177.     for line in res.stdout.readlines():
  178.       match = re.match(r'\s*(.*?):\s*(.*)', line.strip())
  179.       if match is not None:
  180.         k, v = match.group(1), match.group(2)
  181.         if k in ('model', 'technology'):
  182.           battery[k] = v
  183.         elif k in ('energy-full', 'energy-full-design', 'energy-rate'):
  184.           battery[k] = float(v[:-2].strip())
  185.     answer += battery['model'] + ' ' + battery.get('technology', '')
  186.     if battery.get('energy-rate', 0) < 7:
  187.       battery['energy-rate'] = 12.0  # fudge factor, my laptop eats 17 watts
  188.     # print "QUACK: %.1f / %.1f" % (battery['energy-full'], battery['energy-rate'])
  189.     omnomnom = battery['energy-full'] / battery['energy-rate']
  190.     answer += ' {approx %.1f hours}' % omnomnom
  191.     if 'energy-full' in battery and 'energy-full-design' in battery:
  192.       decay = ((battery['energy-full-design'] - battery['energy-full']) * 100) / battery['energy-full-design']
  193.       if decay > 1:
  194.         answer += ' (lost %d%% of max capacity)' % decay
  195.     answer += "\n"
  196.   return answer.strip()
  197.  
  198.  
  199. class StupidGTK:
  200.   " Because GTK wants an entire class for the one object "
  201.  
  202.   def make_label(self):
  203.     result = []
  204.     result.append("<b>Processor</b>")
  205.     result.append(prettyCPUs(getCPUs()))
  206.     result.append("<b>Disk Drives</b>")
  207.     result.append(prettyDiskSizes(getDiskSizes()))
  208.     result.append("<b>Memory Size</b>")
  209.     result.append(prettyMemInfo(getMemInfo()))
  210.     result.append("<b>Linux version</b>")
  211.     result.append(prettyDistro())
  212.     result.append(prettyKernel())
  213.     result.append("<b>Battery Life</b>")
  214.     result.append(prettyBattery())
  215.     result.append("<b>Video Cards</b>")
  216.     result.append(prettyVGAcard())
  217.     result.append("<b>Screen size</b>")
  218.     result.append(prettyScreensize())
  219.     result.append(prettyScreenDiag())
  220.     return '\n'.join(result)
  221.  
  222.   def __init__(self):
  223.     self.window1 = gtk.Window(gtk.WINDOW_TOPLEVEL)
  224.     self.window1.set_border_width(10)
  225.     self.window1.connect('destroy', lambda i: gtk.main_quit())
  226.     self.window1.set_title("HW List for Mom")
  227.    
  228.     self.box1 = gtk.VBox(False, 7)
  229.    
  230.     self.label1 = gtk.Label()
  231.     #self.label1.set_text(self.make_label())
  232.     self.label1.set_markup(self.make_label())
  233.     self.label1.set_selectable(True)
  234.     self.box1.pack_start(self.label1, True, True, 0)
  235.  
  236.     self.button1 = gtk.Button("Okay")
  237.     self.button1.connect_object('clicked', gtk.Widget.destroy, self.window1)
  238.     self.box1.pack_end(self.button1, False, False, 0)
  239.  
  240.     self.window1.add(self.box1)
  241.  
  242.     self.window1.show_all()  # gotta be a better way than just "all"
  243.  
  244.   def main(self):
  245.     gtk.main()
  246.  
  247.  
  248. if __name__ == '__main__':
  249.   WIND = StupidGTK()
  250.   WIND.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement