annotate bio/management/commands/avatar_cleanup.py @ 697:67f8d49a9377

Cleaned up the code a bit. Separated the S3 stuff out into its own class. This class maybe should be in core. Still want to do some kind of context manager around the temporary file we are creating to ensure it gets deleted.
author Brian Neal <bgneal@gmail.com>
date Sun, 08 Sep 2013 21:02:58 -0500
parents 644f69e1c1e1
children
rev   line source
bgneal@668 1 """avatar_cleanup - a management command to remove orphaned avatar files."""
bgneal@668 2
bgneal@668 3 from optparse import make_option
bgneal@668 4 import os
bgneal@668 5
bgneal@668 6 from django.core.management.base import NoArgsCommand
bgneal@668 7 from django.conf import settings
bgneal@668 8
bgneal@668 9 from bio.models import UserProfile
bgneal@668 10
bgneal@668 11
bgneal@668 12 class Command(NoArgsCommand):
bgneal@668 13 help = "Finds and optionally deletes orphan avatar files"
bgneal@668 14 option_list = NoArgsCommand.option_list + (
bgneal@668 15 make_option('--delete',
bgneal@668 16 action='store_true',
bgneal@668 17 dest='delete',
bgneal@668 18 default=False,
bgneal@668 19 help='Delete orphan files'),
bgneal@668 20 )
bgneal@668 21
bgneal@668 22 def handle_noargs(self, **options):
bgneal@668 23 """Find and optionally delete orphan avatar files."""
bgneal@668 24
bgneal@668 25 delete = options.get('delete', False)
bgneal@668 26
bgneal@668 27 orphans = set()
bgneal@668 28 missing = []
bgneal@668 29
bgneal@668 30 avatar_dir = os.path.join(settings.MEDIA_ROOT, settings.AVATAR_DIR)
bgneal@668 31 default_avatar = os.path.join(avatar_dir,
bgneal@668 32 settings.AVATAR_DEFAULT_URL.split('/')[-1])
bgneal@668 33
bgneal@668 34 # find the set of all files in the downloads area
bgneal@668 35 for root, dirs, files in os.walk(avatar_dir, followlinks=True):
bgneal@668 36 for name in files:
bgneal@668 37 orphans.add(unicode(os.path.join(root, name), 'utf-8'))
bgneal@668 38
bgneal@668 39 try:
bgneal@668 40 orphans.remove(default_avatar)
bgneal@668 41 except KeyError:
bgneal@668 42 self.stderr.write("Default avatar file missing! - {}\n".format(
bgneal@668 43 default_avatar))
bgneal@668 44
bgneal@668 45 # examine the UserProfile objects
bgneal@668 46 for profile in UserProfile.objects.iterator():
bgneal@668 47 if profile.avatar:
bgneal@668 48 try:
bgneal@668 49 orphans.remove(profile.avatar.path)
bgneal@668 50 except KeyError:
bgneal@668 51 missing.append(profile)
bgneal@668 52
bgneal@668 53 if orphans and delete:
bgneal@668 54 for path in orphans:
bgneal@668 55 self.stdout.write("Deleting: {}\n".format(path))
bgneal@668 56 os.remove(path)
bgneal@668 57 elif orphans:
bgneal@668 58 self.stdout.write("Orphan files:\n")
bgneal@668 59 for orphan in orphans:
bgneal@668 60 self.stdout.write("{}\n".format(orphan))
bgneal@668 61
bgneal@668 62 if missing:
bgneal@668 63 self.stdout.write("Users with missing avatar files:\n")
bgneal@668 64 for profile in missing:
bgneal@668 65 self.stdout.write("{}\n".format(profile.user.username))
bgneal@668 66
bgneal@668 67 empty_dirs = []
bgneal@668 68 # check for empty directories after deletions
bgneal@668 69 for root, dirs, files in os.walk(avatar_dir, followlinks=True):
bgneal@668 70 if not len(dirs) and not len(files):
bgneal@668 71 empty_dirs.append(root)
bgneal@668 72
bgneal@668 73 if empty_dirs and delete:
bgneal@668 74 for path in empty_dirs:
bgneal@668 75 self.stdout.write("Deleting empty dir: {}\n".format(path))
bgneal@668 76 os.removedirs(path)
bgneal@668 77 elif empty_dirs:
bgneal@668 78 self.stdout.write("Empty directories:\n")
bgneal@668 79 for d in empty_dirs:
bgneal@668 80 self.stdout.write("{}\n".format(d))