Ejemplo n.º 1
0
    def handle(self, *args, **options):
        """command handle function. retrieves tags by id
        """
        try:
            from_tag_ids = parse_tag_ids(options['from'])
            to_tag_ids = parse_tag_ids(options['to'])
        except:
            raise CommandError('Tag IDs must be integer')

        in_both = from_tag_ids & to_tag_ids
        if in_both:
            tag_str = ', '.join([str(i) for i in in_both])
            if len(in_both) > 1:
                error_message = 'Tags with IDs %s appear ' % tag_str
            else:
                error_message = 'Tag with ID %s appears ' % tag_str
            raise CommandError(error_message + 'in both --from and --to sets')

        from_tags = get_tags_by_ids(from_tag_ids)
        to_tags = get_tags_by_ids(to_tag_ids)
        admin = get_admin(options['user_id'])

        exercises = models.Thread.objects.all()
        for from_tag in from_tags:
            exercises = exercises.filter(tags=from_tag)

        #print some feedback here and give a chance to bail out
        exercise_count = exercises.count()
        if exercise_count == 0:
            print """Did not find any matching exercises,
you might want to run prune_unused_tags
or repost a bug, if that does not help"""
        elif exercise_count == 1:
            print "One exercise matches:"
        elif exercise_count <= 10:
            print "%d exercises match:" % exercise_count
        if exercise_count > 10:
            print "%d exercises match." % exercise_count
            print "First 10 are:"
        for exercise in exercises[:10]:
            print '* %s' % exercise.title.strip()

        from_tag_names = format_tag_name_list(from_tags)
        to_tag_names = format_tag_name_list(to_tags)

        prompt = 'Rename tags %s --> %s?' % (from_tag_names, to_tag_names)
        choice = console.choice_dialog(prompt, choices=('yes', 'no'))
        if choice == 'no':
            print 'Canceled'
            sys.exit()
        else:
            sys.stdout.write('Processing:')

        #actual processing stage, only after this point we start to
        #modify stuff in the database, one exercise per transaction
        from_tag_names = get_tag_names(from_tags)
        to_tag_names = get_tag_names(to_tags)
        i = 0
        for exercise in exercises:
            tag_names = set(exercise.get_tag_names())
            tag_names.update(to_tag_names)
            tag_names.difference_update(from_tag_names)

            admin.retag_exercise(
                exercise=exercise._exercise_post(),
                tags=u' '.join(tag_names),
                #silent = True #do we want to timestamp activity on exercise
            )
            i += 1
            sys.stdout.write('%6.2f%%' %
                             (100 * float(i) / float(exercise_count)))
            sys.stdout.write('\b' * 7)
            sys.stdout.flush()

        sys.stdout.write('\n')
Ejemplo n.º 2
0
    def handle(self, *args, **options):
        """command handle function. retrieves tags by id
        """
        try:
            tag_ids = parse_tag_ids(options['tags'])
        except:
            raise CommandError('Tag IDs must be integer')

        from_tags = get_tags_by_ids(tag_ids)
        admin = get_admin(options['user_id'])

        question_list = models.Thread.objects.all()
        for from_tag in from_tags:
            questions = question_list.filter(tags=from_tag)


            #print some feedback here and give a chance to bail out
            question_count = questions.count()
            if question_count == 0:
                print """Did not find any matching questions."""
                from_tag.delete()
                sys.stdout.write('Erased Tag %s\n' % from_tag.name)
                continue
            elif question_count == 1:
                print "One question matches:"
            elif question_count <= 10:
                print "%d questions match:" % question_count
            if question_count > 10:
                print "%d questions match." % question_count
                print "First 10 are:"
            for question in questions[:10]:
                print '* %s' % question.title.strip()


            prompt = 'Remove tags %s ?' % (from_tag.name)
            choice = console.choice_dialog(prompt, choices=('yes', 'no'))
            if choice == 'no':
                print 'Canceled'
                continue
            else:
                sys.stdout.write('Processing:')

            #actual processing stage, only after this point we start to
            #modify stuff in the database, one question per transaction
            from_tag_names = get_tag_names([from_tag])
            i = 0
            skip = 0
            for question in questions:
                tag_names = set(question.get_tag_names())
                orig = "%s" % tag_names
                # If it's the only tag, keep it
                if len(tag_names) == 1:
                    skip += 1
                    continue

                tag_names.difference_update(from_tag_names)

                print "%s -> %s" % (orig, tag_names)
                admin.retag_question(
                    question = question._question_post(),
                    tags = u' '.join(tag_names),
                    #silent = True #do we want to timestamp activity on question
                  )
                i += 1
                sys.stdout.write('%6.2f%%' % (100*float(i)/float(question_count)))
                sys.stdout.write('\b'*7)
                sys.stdout.flush()

            sys.stdout.write('\n')
            #transaction.commit()
            if skip < 1:
              # delete Tag from database
              #from_tag.delete()
              sys.stdout.write('Erased Tag %s\n' % from_tag_names)
            else:
                sys.stdout.write('Skipped %d Questions\n' % skip)
Ejemplo n.º 3
0
    def run_command(self, lang):
        """method that runs the actual command"""
        #go through tags and find character case duplicates and eliminate them
        translation.activate(lang)
        tagnames = models.Tag.objects.filter(
                                language_code=lang
                            ).values_list('name', flat=True)
        self.admin = get_admin()

        #1) first we go through all tags and
        #either fix or delete illegal tags
        found_count = 0

        for name in tagnames:
            try:
                tag = models.Tag.objects.get(
                                        name=name,
                                        language_code=lang
                                    )
            except models.Tag.DoesNotExist:
                #tag with this name was already deleted,
                #because it was an invalid duplicate version
                #of other valid tag
                continue


            fixed_name = get_valid_tag_name(tag)

            #if fixed name is empty after cleaning, delete the tag
            if fixed_name == '':
                print 'Deleting invalid tag: %s' % name
                tag.delete()
                found_count += 1
                continue

            if fixed_name != name:
                print 'Renaming tag: %s -> %s' % (name, fixed_name)

            #if tag name changed, see if there is a duplicate
            #with the same name, in which case we re-assign questions
            #with the current tag to that other duplicate
            #then delete the current tag as no longer used
            if fixed_name != name:
                try:
                    duplicate_tag = models.Tag.objects.get(
                                                name=fixed_name,
                                                language_code=lang
                                            )
                except models.Tag.DoesNotExist:
                    pass
                self.retag_threads([tag], duplicate_tag)
                tag.delete()
                found_count += 1
                continue


            #if there are case variant dupes, we assign questions
            #from the case variants to the current tag and
            #delete the case variant tags
            dupes = models.Tag.objects.filter(
                                name__iexact=fixed_name,
                                language_code=lang
                            ).exclude(pk=tag.id)

            dupes_count = dupes.count()
            if dupes_count:
                self.retag_threads(dupes, tag)
                dupes.delete()
                found_count += dupes_count

            if tag.name != fixed_name:
                tag.name = fixed_name
                tag.save()

        transaction.commit()

        #2) go through questions and fix tag records on each
        # and recalculate all the denormalised tag names on threads
        threads = models.Thread.objects.all()
        checked_count = 0
        total_count = threads.count()
        print "Searching for questions with inconsistent copies of tag records:",
        for thread in threads:
            #make sure that denormalized tag set is the same as normalized
            #we just add both the tags together and try to apply them
            #to the question
            tags = thread.tags.all()
            denorm_tag_set = set(thread.get_tag_names())
            norm_tag_set = set(thread.tags.values_list('name', flat=True))

            if norm_tag_set != denorm_tag_set:
                denorm_tag_set.update(norm_tag_set)
                cleaned_tag_set = set(
                            models.Tag.objects.filter(
                                name__in=denorm_tag_set,
                                language_code=lang
                            ).values_list('name', flat=True)
                        )
                self.admin.retag_question(
                    question=thread._question_post(),
                    tags=' '.join(cleaned_tag_set)
                )

            transaction.commit()
            checked_count += 1
            console.print_progress(checked_count, total_count)
        console.print_progress(checked_count, total_count)

        if found_count:
            print '%d problem questions found, tag records restored' % found_count
        else:
            print 'Did not find any problems'
Ejemplo n.º 4
0
    def handle(self, *args, **options):
        """command handle function. retrieves tags by id
        """
        translation.activate(django_settings.LANGUAGE_CODE)
        try:
            from_tag_ids = parse_tag_ids(options['from'])
            to_tag_ids = parse_tag_ids(options['to'])
        except:
            raise CommandError('Tag IDs must be integer')

        in_both = from_tag_ids & to_tag_ids
        if in_both:
            tag_str = ', '.join([str(i) for i in in_both])
            if len(in_both) > 1:
                error_message = 'Tags with IDs %s appear ' % tag_str
            else:
                error_message = 'Tag with ID %s appears ' % tag_str
            raise CommandError(error_message + 'in both --from and --to sets')

        from_tags = get_tags_by_ids(from_tag_ids)
        to_tags = get_tags_by_ids(to_tag_ids)
        admin = get_admin(options['user_id'])

        questions = models.Thread.objects.all()
        for from_tag in from_tags:
            questions = questions.filter(tags=from_tag)

        #print some feedback here and give a chance to bail out
        question_count = questions.count()
        if question_count == 0:
            print """Did not find any matching questions,
you might want to run prune_unused_tags
or repost a bug, if that does not help"""
        elif question_count == 1:
            print "One question matches:"
        elif question_count <= 10:
            print "%d questions match:" % question_count
        if question_count > 10:
            print "%d questions match." % question_count
            print "First 10 are:"
        for question in questions[:10]:
            print '* %s' % question.title.strip()

        formatted_from_tag_names = format_tag_name_list(from_tags)
        formatted_to_tag_names = format_tag_name_list(to_tags)

        if not options.get('is_force', False):
            prompt = 'Rename tags %s --> %s?' % (formatted_from_tag_names, formatted_to_tag_names)
            choice = console.choice_dialog(prompt, choices=('yes', 'no'))
            if choice == 'no':
                print 'Canceled'
                sys.exit()
        else:
            print 'Renaming tags %s --> %s' % (formatted_from_tag_names, formatted_to_tag_names)
        sys.stdout.write('Processing:')

        from_tag_names = get_tag_names(from_tags)
        to_tag_names = get_tag_names(to_tags)

        #if user provided tag1 as to_tag, and tagsynonym tag1->tag2 exists.
        for to_tag_name in to_tag_names:
            try:
               tag_synonym =  models.TagSynonym.objects.get(source_tag_name = to_tag_name)
               raise CommandError(u'You gave %s as --to argument, but TagSynonym: %s -> %s exists, probably you want to provide %s as --to argument' % (to_tag_name, tag_synonym.source_tag_name, tag_synonym.target_tag_name, tag_synonym.target_tag_name))
            except models.TagSynonym.DoesNotExist:
                pass
        
        
        #actual processing stage, only after this point we start to
        #modify stuff in the database, one question per transaction
        i = 0
        for question in questions:
            tag_names = set(question.get_tag_names())
            tag_names.update(to_tag_names)
            tag_names.difference_update(from_tag_names)

            admin.retag_question(
                question = question._question_post(),
                tags = u' '.join(tag_names),
                #silent = True #do we want to timestamp activity on question
            )
            question.invalidate_cached_thread_content_fragment()
            i += 1
            sys.stdout.write('%6.2f%%' % (100*float(i)/float(question_count)))
            sys.stdout.write('\b'*7)
            sys.stdout.flush()

        sys.stdout.write('\n')
        #transaction.commit()

        #may need to run assertions on that there are
        #print 'Searching for similar tags...',
        #leftover_questions = models.Thread.objects.filter(
        #                        icontains=from_tag.name
        #                    )
        #if leftover_questions.count() > 0:
        #    tag_strings = leftover_questions.values_list('tagnames', flat=True)
        #    similar_tags = get_similar_tags_from_strings(
        #                                        tag_strings,
        #                                        from_tag.name
        #                                    )
        #    print '%d found:' % len(similar_tags),
        #    print '\n*'.join(sorted(list(similar_tags)))
        #else:
        #    print "None found."
        #print "Done."
        #transaction.commit()

        # A user wants to rename tag2->tag3 and tagsynonym tag1->tag2 exists.
        # we want to update tagsynonym (tag1->tag2) to (tag1->tag3)
        for from_tag_name in from_tag_names:
            # we need db_index for target_tag_name as well for this
            models.TagSynonym.objects.filter(target_tag_name = from_tag_name).update(target_tag_name = to_tag_name) 
Ejemplo n.º 5
0
    def run_command(self, lang):
        """method that runs the actual command"""
        #go through tags and find character case duplicates and eliminate them
        translation.activate(lang)
        tagnames = models.Tag.objects.filter(language_code=lang).values_list(
            'name', flat=True)
        self.admin = get_admin()

        #1) first we go through all tags and
        #either fix or delete illegal tags
        found_count = 0

        for name in tagnames:
            try:
                tag = models.Tag.objects.get(name=name, language_code=lang)
            except models.Tag.DoesNotExist:
                #tag with this name was already deleted,
                #because it was an invalid duplicate version
                #of other valid tag
                continue

            fixed_name = get_valid_tag_name(tag)

            #if fixed name is empty after cleaning, delete the tag
            if fixed_name == '':
                print 'Deleting invalid tag: %s' % name
                tag.delete()
                found_count += 1
                continue

            if fixed_name != name:
                print 'Renaming tag: %s -> %s' % (name, fixed_name)

            #if tag name changed, see if there is a duplicate
            #with the same name, in which case we re-assign questions
            #with the current tag to that other duplicate
            #then delete the current tag as no longer used
            if fixed_name != name:
                try:
                    duplicate_tag = models.Tag.objects.get(name=fixed_name,
                                                           language_code=lang)
                except models.Tag.DoesNotExist:
                    pass
                self.retag_threads([tag], duplicate_tag)
                tag.delete()
                found_count += 1
                continue

            #if there are case variant dupes, we assign questions
            #from the case variants to the current tag and
            #delete the case variant tags
            dupes = models.Tag.objects.filter(
                name__iexact=fixed_name, language_code=lang).exclude(pk=tag.id)

            dupes_count = dupes.count()
            if dupes_count:
                self.retag_threads(dupes, tag)
                dupes.delete()
                found_count += dupes_count

            if tag.name != fixed_name:
                tag.name = fixed_name
                tag.save()

        transaction.commit()

        #2) go through questions and fix tag records on each
        # and recalculate all the denormalised tag names on threads
        threads = models.Thread.objects.all()
        checked_count = 0
        total_count = threads.count()
        print "Searching for questions with inconsistent copies of tag records:",
        for thread in threads:
            #make sure that denormalized tag set is the same as normalized
            #we just add both the tags together and try to apply them
            #to the question
            tags = thread.tags.all()
            denorm_tag_set = set(thread.get_tag_names())
            norm_tag_set = set(thread.tags.values_list('name', flat=True))

            if norm_tag_set != denorm_tag_set:
                denorm_tag_set.update(norm_tag_set)
                cleaned_tag_set = set(
                    models.Tag.objects.filter(name__in=denorm_tag_set,
                                              language_code=lang).values_list(
                                                  'name', flat=True))
                self.admin.retag_question(question=thread._question_post(),
                                          tags=' '.join(cleaned_tag_set))

            transaction.commit()
            checked_count += 1
            console.print_progress(checked_count, total_count)
        console.print_progress(checked_count, total_count)

        if found_count:
            print '%d problem questions found, tag records restored' % found_count
        else:
            print 'Did not find any problems'
Ejemplo n.º 6
0
    def handle(self, *args, **options):
        """command handle function. reads tag names, decodes
        them using the standard input encoding and attempts to find
        the matching tags

        If "from" tag is not resolved, command fails
        if "to" tag is not resolved, a new tag is created
        """

        if options['from'] is None:
            raise CommandError('the --from argument is required')
        if options['to'] is None:
            raise CommandError('the --to argument is required')

        source_tag_name = decode_input(options['from'])
        target_tag_name = decode_input(options['to'])

        if source_tag_name == target_tag_name:
            raise CommandError("source and target tags appear to be the same")

        admin = get_admin(seed_user_id=options['user_id'])

        source_tag = None
        is_source_tag_created = False

        try:
            source_tag = Tag.objects.get(name=source_tag_name, language_code=options['lang'])
        except Tag.DoesNotExist:
            if not options.get('is_force', False):
                prompt = """source tag %s doesn't exist, are you sure you want to create a TagSynonym
    %s ==> %s?""" % (source_tag_name, source_tag_name, target_tag_name)
                choice = console.choice_dialog(prompt, choices=('yes', 'no'))
                if choice == 'no':
                    print('Cancled')
                    sys.exit()
            source_tag = Tag.objects.create(name=source_tag_name, created_by=admin, language_code=options['lang'])
            is_source_tag_created = True

        # test if target_tag is actually synonym for yet another tag
        # when user asked tag2->tag3, we already had tag3->tag4.
        try:
            tag_synonym_tmp = TagSynonym.objects.get(source_tag_name=target_tag_name, language_code=options['lang'])
            if not options.get('is_force', False):
                prompt = """There exists a TagSynonym %s ==> %s,
    hence we will create a tag synonym %s ==> %s instead. Proceed?""" % (
                    tag_synonym_tmp.source_tag_name, tag_synonym_tmp.target_tag_name, source_tag_name,
                    tag_synonym_tmp.target_tag_name)
                choice = console.choice_dialog(prompt, choices=('yes', 'no'))
                if choice == 'no':
                    print('Cancled')
                    sys.exit()
            target_tag_name = tag_synonym_tmp.target_tag_name
            options['to'] = target_tag_name
        except TagSynonym.DoesNotExist:
            pass

        try:
            Tag.objects.get(name=target_tag_name, language_code=options['lang'])
        except Tag.DoesNotExist:
            # we are creating a target tag, let's copy source tag's info
            # used_count are updated later
            Tag.objects.create(name=target_tag_name, created_by=admin, status=source_tag.status,
                               tag_wiki=source_tag.tag_wiki, language_code=options['lang'])

        tag_synonym_tmp, created = TagSynonym.objects.get_or_create(
            source_tag_name=source_tag_name, target_tag_name=target_tag_name, owned_by=admin,
            language_code=options['lang'])

        management.call_command('rename_tags', *args, **options)

        # When source_tag_name is a target_tag_name of already existing TagSynonym.
        # ie. if tag1->tag2 exists when user asked tag2->tag3
        # we are going to convert all tag1->tag2 to tag1->tag3 as well
        qs = TagSynonym.objects.filter(target_tag_name=source_tag_name, language_code=options['lang'])
        for existing_tag_synonym in qs:
            new_options = options.copy()
            new_options['from'] = existing_tag_synonym.source_tag_name
            new_options['user_id'] = admin.id
            new_options['is_force'] = True  # this is mandatory conversion
            new_options['timestamp'] = timezone.now()
            existing_tag_synonym.delete()  # no longer needed
            self.handle(*args, **new_options)

        # delete source Tag
        if is_source_tag_created:
            source_tag.delete()
        else:
            source_tag.deleted = True
            source_tag.deleted_at = options.get('timestamp', timezone.now())
            source_tag.deleted_by = admin
Ejemplo n.º 7
0
    def handle(self, *args, **options):
        """command handle function. reads tag names, decodes
        them using the standard input encoding and attempts to find
        the matching tags

        If "from" tag is not resolved, command fails
        if "to" tag is not resolved, a new tag is created
        """

        if options['from'] is None:
            raise CommandError('the --from argument is required')
        if options['to'] is None:
            raise CommandError('the --to argument is required')

        source_tag_name = decode_input(options['from'])
        target_tag_name = decode_input(options['to'])

        if source_tag_name == target_tag_name:
            raise CommandError("source and target tags appear to be the same")

        admin = get_admin(seed_user_id=options['user_id'])

        source_tag = None
        is_source_tag_created = False

        try:
            source_tag = Tag.objects.get(name=source_tag_name,
                                         language_code=options['lang'])
        except Tag.DoesNotExist:
            if not options.get('is_force', False):
                prompt = """source tag %s doesn't exist, are you sure you want to create a TagSynonym
    %s ==> %s?""" % (source_tag_name, source_tag_name, target_tag_name)
                choice = console.choice_dialog(prompt, choices=('yes', 'no'))
                if choice == 'no':
                    print('Cancled')
                    sys.exit()
            source_tag = Tag.objects.create(name=source_tag_name,
                                            created_by=admin,
                                            language_code=options['lang'])
            is_source_tag_created = True

        # test if target_tag is actually synonym for yet another tag
        # when user asked tag2->tag3, we already had tag3->tag4.
        try:
            tag_synonym_tmp = TagSynonym.objects.get(
                source_tag_name=target_tag_name, language_code=options['lang'])
            if not options.get('is_force', False):
                prompt = """There exists a TagSynonym %s ==> %s,
    hence we will create a tag synonym %s ==> %s instead. Proceed?""" % (
                    tag_synonym_tmp.source_tag_name,
                    tag_synonym_tmp.target_tag_name, source_tag_name,
                    tag_synonym_tmp.target_tag_name)
                choice = console.choice_dialog(prompt, choices=('yes', 'no'))
                if choice == 'no':
                    print('Cancled')
                    sys.exit()
            target_tag_name = tag_synonym_tmp.target_tag_name
            options['to'] = target_tag_name
        except TagSynonym.DoesNotExist:
            pass

        try:
            Tag.objects.get(name=target_tag_name,
                            language_code=options['lang'])
        except Tag.DoesNotExist:
            # we are creating a target tag, let's copy source tag's info
            # used_count are updated later
            Tag.objects.create(name=target_tag_name,
                               created_by=admin,
                               status=source_tag.status,
                               tag_wiki=source_tag.tag_wiki,
                               language_code=options['lang'])

        tag_synonym_tmp, created = TagSynonym.objects.get_or_create(
            source_tag_name=source_tag_name,
            target_tag_name=target_tag_name,
            owned_by=admin,
            language_code=options['lang'])

        management.call_command('rename_tags', *args, **options)

        # When source_tag_name is a target_tag_name of already existing TagSynonym.
        # ie. if tag1->tag2 exists when user asked tag2->tag3
        # we are going to convert all tag1->tag2 to tag1->tag3 as well
        qs = TagSynonym.objects.filter(target_tag_name=source_tag_name,
                                       language_code=options['lang'])
        for existing_tag_synonym in qs:
            new_options = options.copy()
            new_options['from'] = existing_tag_synonym.source_tag_name
            new_options['user_id'] = admin.id
            new_options['is_force'] = True  # this is mandatory conversion
            new_options['timestamp'] = timezone.now()
            existing_tag_synonym.delete()  # no longer needed
            self.handle(*args, **new_options)

        # delete source Tag
        if is_source_tag_created:
            source_tag.delete()
        else:
            source_tag.deleted = True
            source_tag.deleted_at = options.get('timestamp', timezone.now())
            source_tag.deleted_by = admin
Ejemplo n.º 8
0
    def handle(self, *args, **options):
        """command handle function. retrieves tags by id
        """
        translation.activate(django_settings.LANGUAGE_CODE)
        try:
            from_tag_ids = parse_tag_ids(options['from'])
            to_tag_ids = parse_tag_ids(options['to'])
        except:
            raise CommandError('Tag IDs must be integer')

        in_both = from_tag_ids & to_tag_ids
        if in_both:
            tag_str = ', '.join([str(i) for i in in_both])
            if len(in_both) > 1:
                error_message = 'Tags with IDs %s appear ' % tag_str
            else:
                error_message = 'Tag with ID %s appears ' % tag_str
            raise CommandError(error_message + 'in both --from and --to sets')

        from_tags = get_tags_by_ids(from_tag_ids)
        to_tags = get_tags_by_ids(to_tag_ids)

        #all tags must belong to the same language
        lang_codes = set(tag.language_code for tag in (from_tags + to_tags))
        if len(lang_codes) != 1:
            langs = ', '.join(lang_codes)
            raise CommandError(
                'all tags must belong to the same language, have: %s' % langs)
        lang = list(lang_codes).pop()

        admin = get_admin(options['user_id'])

        questions = models.Thread.objects.all()
        for from_tag in from_tags:
            questions = questions.filter(tags=from_tag)

        #print some feedback here and give a chance to bail out
        question_count = questions.count()
        if question_count == 0:
            print("""Did not find any matching questions,
you might want to run prune_unused_tags
or repost a bug, if that does not help""")
        elif question_count == 1:
            print("One question matches:")
        elif question_count <= 10:
            print("%d questions match:" % question_count)
        if question_count > 10:
            print("%d questions match." % question_count)
            print("First 10 are:")
        for question in questions[:10]:
            print('* %s' % question.title.strip())

        formatted_from_tag_names = format_tag_name_list(from_tags)
        formatted_to_tag_names = format_tag_name_list(to_tags)

        if not options.get('is_force', False):
            prompt = 'Rename tags %s --> %s?' % (formatted_from_tag_names,
                                                 formatted_to_tag_names)
            choice = console.choice_dialog(prompt, choices=('yes', 'no'))
            if choice == 'no':
                print('Canceled')
                sys.exit()
        else:
            print('Renaming tags %s --> %s' %
                  (formatted_from_tag_names, formatted_to_tag_names))
        sys.stdout.write('Processing:')

        from_tag_names = get_tag_names(from_tags)
        to_tag_names = get_tag_names(to_tags)

        #if user provided tag1 as to_tag, and tagsynonym tag1->tag2 exists.
        for to_tag_name in to_tag_names:
            try:
                tag_synonym = models.TagSynonym.objects.get(
                    source_tag_name=to_tag_name, language_code=lang)
                raise CommandError(
                    u'You gave %s as --to argument, but TagSynonym: %s -> %s exists, probably you want to provide %s as --to argument'
                    %
                    (to_tag_name, tag_synonym.source_tag_name,
                     tag_synonym.target_tag_name, tag_synonym.target_tag_name))
            except models.TagSynonym.DoesNotExist:
                pass

        #actual processing stage, only after this point we start to
        #modify stuff in the database, one question per transaction
        i = 0
        for question in questions:
            tag_names = set(question.get_tag_names())
            tag_names.update(to_tag_names)
            tag_names.difference_update(from_tag_names)

            admin.retag_question(
                question=question._question_post(),
                tags=u' '.join(tag_names),
                #silent = True #do we want to timestamp activity on question
            )
            question.invalidate_cached_summary_html()
            i += 1
            sys.stdout.write('%6.2f%%' %
                             (100 * float(i) / float(question_count)))
            sys.stdout.write('\b' * 7)
            sys.stdout.flush()

        sys.stdout.write('\n')

        #may need to run assertions on that there are
        #print 'Searching for similar tags...',
        #leftover_questions = models.Thread.objects.filter(
        #                        icontains=from_tag.name
        #                    )
        #if leftover_questions.count() > 0:
        #    tag_strings = leftover_questions.values_list('tagnames', flat=True)
        #    similar_tags = get_similar_tags_from_strings(
        #                                        tag_strings,
        #                                        from_tag.name
        #                                    )
        #    print '%d found:' % len(similar_tags),
        #    print '\n*'.join(sorted(list(similar_tags)))
        #else:
        #    print "None found."
        #print "Done."

        # A user wants to rename tag2->tag3 and tagsynonym tag1->tag2 exists.
        # we want to update tagsynonym (tag1->tag2) to (tag1->tag3)
        for from_tag_name in from_tag_names:
            # we need db_index for target_tag_name as well for this
            models.TagSynonym.objects.filter(
                target_tag_name=from_tag_name,
                language_code=lang).update(target_tag_name=to_tag_name)
Ejemplo n.º 9
0
    def handle(self, *args, **options):
        """command handle function. retrieves tags by id
        """
        try:
            from_tag_ids = parse_tag_ids(options['from'])
            to_tag_ids = parse_tag_ids(options['to'])
        except:
            raise CommandError('Tag IDs must be integer')

        in_both = from_tag_ids & to_tag_ids
        if in_both:
            tag_str = ', '.join([str(i) for i in in_both])
            if len(in_both) > 1:
                error_message = 'Tags with IDs %s appear ' % tag_str
            else:
                error_message = 'Tag with ID %s appears ' % tag_str
            raise CommandError(error_message + 'in both --from and --to sets')

        from_tags = get_tags_by_ids(from_tag_ids)
        to_tags = get_tags_by_ids(to_tag_ids)
        admin = get_admin(options['user_id'])

        questions = models.Question.objects.all()
        for from_tag in from_tags:
            questions = questions.filter(tags = from_tag)

        #print some feedback here and give a chance to bail out
        question_count = questions.count()
        if question_count == 0:
            print """Did not find any matching questions,
you might want to run prune_unused_tags
or repost a bug, if that does not help"""
        elif question_count == 1:
            print "One question matches:"
        elif question_count <= 10:
            print "%d questions match:" % question_count
        if question_count > 10:
            print "%d questions match." % question_count
            print "First 10 are:"
        for question in questions[:10]:
            print '* %s' % question.thread.title.strip()

        from_tag_names = format_tag_name_list(from_tags)
        to_tag_names = format_tag_name_list(to_tags)

        prompt = 'Rename tags %s --> %s?' % (from_tag_names, to_tag_names)
        choice = console.choice_dialog(prompt, choices=('yes', 'no'))
        if choice == 'no':
            print 'Canceled'
            sys.exit()
        else:
            sys.stdout.write('Processing:')

        #actual processing stage, only after this point we start to
        #modify stuff in the database, one question per transaction
        from_tag_names = get_tag_names(from_tags)
        to_tag_names = get_tag_names(to_tags)
        i = 0
        for question in questions:
            tag_names = set(question.get_tag_names())
            tag_names.update(to_tag_names)
            tag_names.difference_update(from_tag_names)

            admin.retag_question(
                question = question,
                tags = u' '.join(tag_names),
                #silent = True #do we want to timestamp activity on question
            )
            i += 1
            sys.stdout.write('%6.2f%%' % (100*float(i)/float(question_count)))
            sys.stdout.write('\b'*7)
            sys.stdout.flush()

        sys.stdout.write('\n')
Ejemplo n.º 10
0
    def handle(self, *args, **options):
        """command handle function. retrieves tags by id
        """
        try:
            tag_ids = parse_tag_ids(options['tags'])
        except:
            raise CommandError('Tag IDs must be integer')

        from_tags = get_tags_by_ids(tag_ids)
        admin = get_admin(options['user_id'])

        question_list = models.Thread.objects.all()
        for from_tag in from_tags:
            questions = question_list.filter(tags=from_tag)

            #print some feedback here and give a chance to bail out
            question_count = questions.count()
            if question_count == 0:
                print """Did not find any matching questions."""
                from_tag.delete()
                sys.stdout.write('Erased Tag %s\n' % from_tag.name)
                continue
            elif question_count == 1:
                print "One question matches:"
            elif question_count <= 10:
                print "%d questions match:" % question_count
            if question_count > 10:
                print "%d questions match." % question_count
                print "First 10 are:"
            for question in questions[:10]:
                print '* %s' % question.title.strip()

            prompt = 'Remove tags %s ?' % (from_tag.name)
            choice = console.choice_dialog(prompt, choices=('yes', 'no'))
            if choice == 'no':
                print 'Canceled'
                continue
            else:
                sys.stdout.write('Processing:')

            #actual processing stage, only after this point we start to
            #modify stuff in the database, one question per transaction
            from_tag_names = get_tag_names([from_tag])
            i = 0
            skip = 0
            for question in questions:
                tag_names = set(question.get_tag_names())
                orig = "%s" % tag_names
                # If it's the only tag, keep it
                if len(tag_names) == 1:
                    skip += 1
                    continue

                tag_names.difference_update(from_tag_names)

                print "%s -> %s" % (orig, tag_names)
                admin.retag_question(
                    question=question._question_post(),
                    tags=u' '.join(tag_names),
                    #silent = True #do we want to timestamp activity on question
                )
                i += 1
                sys.stdout.write('%6.2f%%' %
                                 (100 * float(i) / float(question_count)))
                sys.stdout.write('\b' * 7)
                sys.stdout.flush()

            sys.stdout.write('\n')
            #transaction.commit()
            if skip < 1:
                # delete Tag from database
                #from_tag.delete()
                sys.stdout.write('Erased Tag %s\n' % from_tag_names)
            else:
                sys.stdout.write('Skipped %d Questions\n' % skip)