breakdown.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import os
  2. import json
  3. from . import common
  4. from . import tsdb
  5. def breakdown_database(subreddit=None, username=None):
  6. '''
  7. Given a database, return a json dict breaking down the submission / comment count for
  8. users (if a subreddit database) or subreddits (if a user database).
  9. '''
  10. if (subreddit is None) == (username is None):
  11. raise Exception('Enter subreddit or username but not both')
  12. breakdown_results = {}
  13. def _ingest(names, subkey):
  14. for name in names:
  15. breakdown_results.setdefault(name, {})
  16. breakdown_results[name].setdefault(subkey, 0)
  17. breakdown_results[name][subkey] += 1
  18. if subreddit:
  19. database = tsdb.TSDB.for_subreddit(subreddit, do_create=False)
  20. else:
  21. database = tsdb.TSDB.for_user(username, do_create=False)
  22. cur = database.sql.cursor()
  23. for table in ['submissions', 'comments']:
  24. if subreddit:
  25. cur.execute('SELECT author FROM %s' % table)
  26. elif username:
  27. cur.execute('SELECT subreddit FROM %s' % table)
  28. names = (row[0] for row in common.fetchgenerator(cur))
  29. _ingest(names, table)
  30. for name in breakdown_results:
  31. breakdown_results[name].setdefault('submissions', 0)
  32. breakdown_results[name].setdefault('comments', 0)
  33. return breakdown_results
  34. def breakdown_argparse(args):
  35. if args.subreddit:
  36. database = tsdb.TSDB.for_subreddit(args.subreddit, do_create=False)
  37. else:
  38. database = tsdb.TSDB.for_user(args.username, do_create=False)
  39. breakdown_results = breakdown_database(
  40. subreddit=args.subreddit,
  41. username=args.username,
  42. )
  43. def sort_name(name):
  44. return name.lower()
  45. def sort_submissions(name):
  46. invert_score = -1 * breakdown_results[name]['submissions']
  47. return (invert_score, name.lower())
  48. def sort_comments(name):
  49. invert_score = -1 * breakdown_results[name]['comments']
  50. return (invert_score, name.lower())
  51. def sort_total_posts(name):
  52. invert_score = breakdown_results[name]['submissions'] + breakdown_results[name]['comments']
  53. invert_score = -1 * invert_score
  54. return (invert_score, name.lower())
  55. breakdown_sorters = {
  56. 'name': sort_name,
  57. 'submissions': sort_submissions,
  58. 'comments': sort_comments,
  59. 'total_posts': sort_total_posts,
  60. }
  61. breakdown_names = list(breakdown_results.keys())
  62. if args.sort is not None:
  63. try:
  64. sorter = breakdown_sorters[args.sort.lower()]
  65. except KeyError:
  66. message = '{sorter} is not a sorter. Choose from {options}'
  67. message = message.format(sorter=args.sort, options=list(breakdown_sorters.keys()))
  68. raise KeyError(message)
  69. breakdown_names.sort(key=sorter)
  70. dump = ' "{name}": {{"submissions": {submissions}, "comments": {comments}}}'
  71. dump = [dump.format(name=name, **breakdown_results[name]) for name in breakdown_names]
  72. dump = ',\n'.join(dump)
  73. dump = '{\n' + dump + '\n}\n'
  74. else:
  75. dump = json.dumps(breakdown_results)
  76. if args.sort is None:
  77. breakdown_basename = '%s_breakdown.json'
  78. else:
  79. breakdown_basename = '%%s_breakdown_%s.json' % args.sort
  80. breakdown_basename = breakdown_basename % database.filepath.replace_extension('').basename
  81. breakdown_filepath = database.breakdown_dir.with_child(breakdown_basename)
  82. breakdown_filepath.parent.makedirs(exist_ok=True)
  83. breakdown_file = breakdown_filepath.open('w')
  84. with breakdown_file:
  85. breakdown_file.write(dump)
  86. print('Wrote', breakdown_filepath.relative_path)
  87. return breakdown_results