comparison core/management/commands/ssl_images.py @ 866:98adae6e13a1

More WIP on ssl_images command.
author Brian Neal <bgneal@gmail.com>
date Thu, 04 Dec 2014 20:32:43 -0600
parents 0ffdb434d2dd
children 64a5acb83937
comparison
equal deleted inserted replaced
865:08bae2b1d2d1 866:98adae6e13a1
24 logger = logging.getLogger(__name__) 24 logger = logging.getLogger(__name__)
25 25
26 IMAGE_LINK_RE = re.compile(markdown.inlinepatterns.IMAGE_LINK_RE) 26 IMAGE_LINK_RE = re.compile(markdown.inlinepatterns.IMAGE_LINK_RE)
27 IMAGE_REF_RE = re.compile(markdown.inlinepatterns.IMAGE_REFERENCE_RE) 27 IMAGE_REF_RE = re.compile(markdown.inlinepatterns.IMAGE_REFERENCE_RE)
28 28
29 MODEL_CHOICES = ['comments', 'posts']
30
29 quit_flag = False 31 quit_flag = False
30 32
31 33
32 def signal_handler(signum, frame): 34 def signal_handler(signum, frame):
33 """SIGINT signal handler""" 35 """SIGINT signal handler"""
42 formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s') 44 formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
43 handler.setFormatter(formatter) 45 handler.setFormatter(formatter)
44 logger.addHandler(handler) 46 logger.addHandler(handler)
45 47
46 48
47 class CommentFacade(object): 49 def replace_image_markup(match):
48 """Wrapper class to provide uniform access to Comments.""" 50 return match.group(0)
49 def __init__(self, comment):
50 self.comment = comment
51
52 @property
53 def text(self):
54 return self.comment.comment
55
56 @text.setter
57 def text(self, value):
58 self.comment.comment = value
59 51
60 52
61 class PostFacade(object): 53 def process_post(text):
62 """Wrapper class to provide uniform access to Forum posts."""
63 def __init__(self, post):
64 self.post = post
65
66 @property
67 def text(self):
68 return self.post.body
69
70 @text.setter
71 def text(self, value):
72 self.post.body = value
73
74
75 def process_post(post):
76 """Process the post object: 54 """Process the post object:
77 55
78 A regex substitution is run on the post's text field. This fixes up image 56 A regex substitution is run on the post's text field. This fixes up image
79 links, getting rid of plain old http sources; either converting to https 57 links, getting rid of plain old http sources; either converting to https
80 or relative style links (if the link is to SG101). 58 or relative style links (if the link is to SG101).
81 59
82 We also do a search for Markdown image reference markup. We aren't expecting 60 We also do a search for Markdown image reference markup. We aren't expecting
83 these, but we will log something if we see any. 61 these, but we will log something if we see any.
84 62
85 """ 63 """
64 return IMAGE_LINK_RE.sub(replace_image_markup, text)
86 65
87 66
88 class Command(NoArgsCommand): 67 class Command(NoArgsCommand):
89 help = "Rewrite forum posts and comments to not use http for images" 68 help = "Rewrite forum posts and comments to not use http for images"
90 option_list = NoArgsCommand.option_list + ( 69 option_list = NoArgsCommand.option_list + (
91 make_option('--forums', 70 make_option('-m', '--model',
92 action='store_true', 71 choices=MODEL_CHOICES,
93 default=False, 72 help="which model to update; must be one of {{{}}}".format(
94 help="process forum posts"), 73 ', '.join(MODEL_CHOICES))),
95 make_option('--comments',
96 action='store_true',
97 default=False,
98 help="process comments"),
99 make_option('-i', '--i', 74 make_option('-i', '--i',
100 type='int', 75 type='int',
101 help="optional first slice index; the i in [i:j]"), 76 help="optional first slice index; the i in [i:j]"),
102 make_option('-j', '--j', 77 make_option('-j', '--j',
103 type='int', 78 type='int',
106 81
107 def handle_noargs(self, **options): 82 def handle_noargs(self, **options):
108 _setup_logging() 83 _setup_logging()
109 logger.info("Starting; arguments received: %s", options) 84 logger.info("Starting; arguments received: %s", options)
110 85
111 do_comments = options['comments'] 86 if options['model'] not in MODEL_CHOICES:
112 do_forums = options['forums'] 87 raise CommandError('Please choose a --model option')
113 if do_comments and do_forums:
114 raise CommandError("Please specify --forums or --comments, not both")
115 elif not do_comments and not do_forums:
116 raise CommandError("Please specify --forums or --comments")
117 88
118 if do_comments: 89 if options['model'] == 'comments':
119 qs = Comment.objects.all() 90 qs = Comment.objects.all()
120 facade = CommentFacade 91 text_attr = 'comment'
121 else: 92 else:
122 qs = Post.objects.all() 93 qs = Post.objects.all()
123 facade = PostFacade 94 text_attr = 'body'
124 95
125 i, j = options['i'], options['j'] 96 i, j = options['i'], options['j']
126 97
127 if i is not None and i < 0: 98 if i is not None and i < 0:
128 raise CommandError("-i must be >= 0") 99 raise CommandError("-i must be >= 0")
143 114
144 s = [] 115 s = []
145 for model in qs.iterator(): 116 for model in qs.iterator():
146 if quit_flag: 117 if quit_flag:
147 logger.warning("SIGINT received, exiting") 118 logger.warning("SIGINT received, exiting")
148 obj = facade(model) 119 txt = getattr(model, text_attr)
149 process_post(obj) 120 new_txt = process_post(txt)
150 s.append(obj.text) 121 s.append(new_txt)
151 122
152 import pprint 123 import pprint
153 pprint.pprint(s) 124 pprint.pprint(s)