def handle_noargs(self, **options): self.verbosity = int(options.get("verbosity", 1)) self.interactive = options.get("interactive") if self.interactive: answer = choice_dialog("This command will DELETE ALL DATA in the current database, fill the database with test data and flush the test data. Are you absolutely sure you want to proceed?", choices = ("yes", "no", )) if answer != "yes": return # First, flush the data self.print_if_verbose("FLUSHING THE DATABASE") management.call_command('flush', verbosity=0, interactive=False) # Then, fill the database with test content self.print_if_verbose("FILLING THE DB WITH TEST CONTENT") management.call_command('askbot_add_test_content', verbosity=0, interactive=False) # At last, dump the data into a fixture # Create a file object ready for writing self.print_if_verbose("DUMPING THE DATA IN FILE '%s'" % FIXTURE_NAME) fixture = open(FIXTURE_NAME, 'wb') management.call_command('dumpdata', stdout = fixture, exclude = EXCLUDE_APPS, indent = 4, natural = True) fixture.close() # FLUSH AGAIN self.print_if_verbose("FLUSHING THE DATABASE") management.call_command('flush', verbosity=0, interactive=False) self.print_if_verbose("You can load this data now by invoking ./manage.py %s" % FIXTURE_NAME)
def handle_noargs(self, **options): self.verbosity = int(options.get("verbosity", 1)) self.interactive = options.get("interactive") if self.interactive: answer = choice_dialog( "This command will DELETE ALL DATA in the current database, and will fill the database with test data. Are you absolutely sure you want to proceed?", choices=( "yes", "no", )) if answer != "yes": return # Create Users users = self.create_users() # Create Questions, vote for questions active_question = self.create_questions(users) # Create Answers, vote for the answers, vote for the active question # vote for the active answer active_answer = self.create_answers(users, active_question) # Create Comments, vote for the active answer active_question_comment, active_answer_comment = self.create_comments( users, active_question, active_answer) # Edit the active question, answer and comments active_question.author.edit_question(question=active_question, title=TITLE_TEMPLATE % "EDITED", body_text=CONTENT_TEMPLATE, revision_comment="EDITED", force=True) self.print_if_verbose("User has edited the active question") active_answer.author.edit_answer(answer=active_answer, body_text=COMMENT_TEMPLATE, force=True) self.print_if_verbose("User has edited the active answer") active_answer_comment.author.edit_comment( comment_post=active_answer_comment, body_text=ANSWER_TEMPLATE) self.print_if_verbose("User has edited the active answer comment") active_question_comment.author.edit_comment( comment_post=active_question_comment, body_text=ANSWER_TEMPLATE) self.print_if_verbose("User has edited the active question comment") # Accept best answer active_question.author.accept_best_answer( answer=active_answer, force=True, ) self.print_if_verbose("User has accepted a best answer") self.print_if_verbose("DONE")
def handle_noargs(self, **options): self.verbosity = int(options.get("verbosity", 1)) self.interactive = options.get("interactive") if self.interactive: answer = choice_dialog( "This command will DELETE ALL DATA in the current database, and will fill the database with test data. Are you absolutely sure you want to proceed?", choices=("yes", "no"), ) if answer != "yes": return translation.activate(django_settings.LANGUAGE_CODE) self.save_alert_settings() self.stop_alerts() # saves time on running the command # Create Users users = self.create_users() # Create Questions, vote for questions active_question = self.create_questions(users) # Create Answers, vote for the answers, vote for the active question # vote for the active answer active_answer = self.create_answers(users, active_question) # Create Comments, vote for the active answer active_question_comment, active_answer_comment = self.create_comments(users, active_question, active_answer) # Edit the active question, answer and comments active_question.author.edit_question( question=active_question, title=TITLE_TEMPLATE % "EDITED", body_text=CONTENT_TEMPLATE, revision_comment="EDITED", force=True, ) self.print_if_verbose("User has edited the active question") active_answer.author.edit_answer(answer=active_answer, body_text=COMMENT_TEMPLATE, force=True) self.print_if_verbose("User has edited the active answer") active_answer_comment.author.edit_comment(comment_post=active_answer_comment, body_text=ANSWER_TEMPLATE) self.print_if_verbose("User has edited the active answer comment") active_question_comment.author.edit_comment(comment_post=active_question_comment, body_text=ANSWER_TEMPLATE) self.print_if_verbose("User has edited the active question comment") # Accept best answer active_question.author.accept_best_answer(answer=active_answer, force=True) self.print_if_verbose("User has accepted a best answer") self.restore_saved_alert_settings() self.print_if_verbose("DONE")
def get_install_directory(force = False): """returns a directory where a new django app/project can be installed. If ``force`` is ``True`` - will permit using a directory with an existing django project. """ from askbot.deployment import messages where_to_deploy_msg = messages.WHERE_TO_DEPLOY directory = raw_input(where_to_deploy_msg + ' ') if directory.strip() == '': return None directory = clean_directory(directory) if directory is None: return None if can_create_path(directory) == False: print(messages.format_msg_dir_not_writable(directory)) return None if os.path.exists(directory): if path_is_clean_for_django(directory): if has_existing_django_project(directory): if not force: print(messages.CANNOT_OVERWRITE_DJANGO_PROJECT % \ {'directory': directory}) return None else: print(messages.format_msg_dir_unclean_django(directory)) return None elif force == False: message = messages.format_msg_create(directory) should_create_new = console.choice_dialog( message, choices = ['yes','no'], invalid_phrase = messages.INVALID_INPUT ) if should_create_new == 'no': return None if dir_taken_by_python_module(directory): print(messages.format_msg_bad_dir_name(directory)) return None if dir_name_unacceptable_for_django_project(directory): print("""\nDirectory %s is not acceptable for a Django project. Please use lower case characters, numbers and underscore. The first character cannot be a number.\n""" % os.path.basename(directory)) return None return directory
def __call__(self): # this is the main part of the original askbot_setup() try: options = self.parser.parse_args() self._set_verbosity(options) self._set_create_project(options) print_message(messages.DEPLOY_PREAMBLE, self.verbosity) # the destination directory directory = path_utils.clean_directory(options.dir_name) while directory is None: directory = path_utils.get_install_directory(force=options.get('force')) # i.e. ask the user options.dir_name = directory if options.database_engine not in DATABASE_ENGINE_CHOICES: options.database_engine = console.choice_dialog( 'Please select database engine:\n1 - for postgresql, ' '2 - for sqlite, 3 - for mysql, 4 - oracle', choices=DATABASE_ENGINE_CHOICES ) options_dict = vars(options) if options.force is False: options_dict = collect_missing_options(options_dict) database_engine_codes = { '1': 'postgresql_psycopg2', '2': 'sqlite3', '3': 'mysql', '4': 'oracle' } database_engine = database_engine_codes[options.database_engine] options_dict['database_engine'] = database_engine self.deploy_askbot(options_dict) if database_engine == 'postgresql_psycopg2': try: import psycopg2 except ImportError: print('\nNEXT STEPS: install python binding for postgresql') print('pip install psycopg2\n') elif database_engine == 'mysql': try: import _mysql except ImportError: print('\nNEXT STEP: install python binding for mysql') print('pip install mysql-python\n') except KeyboardInterrupt: print("\n\nAborted.") sys.exit(1) pass
def get_install_directory(force = False): """returns a directory where a new django app/project can be installed. If ``force`` is ``True`` - will permit using a directory with an existing django project. """ from askbot.deployment import messages where_to_deploy_msg = messages.WHERE_TO_DEPLOY directory = raw_input(where_to_deploy_msg + ' ') if directory.strip() == '': return None directory = clean_directory(directory) if directory is None: return None if can_create_path(directory) == False: print messages.format_msg_dir_not_writable(directory) return None if os.path.exists(directory): if path_is_clean_for_django(directory): if has_existing_django_project(directory): if not force: print messages.CANNOT_OVERWRITE_DJANGO_PROJECT % \ {'directory': directory} return None else: print messages.format_msg_dir_unclean_django(directory) return None elif force == False: message = messages.format_msg_create(directory) should_create_new = console.choice_dialog( message, choices = ['yes','no'], invalid_phrase = messages.INVALID_INPUT ) if should_create_new == 'no': return None if dir_taken_by_python_module(directory): print messages.format_msg_bad_dir_name(directory) return None if dir_name_unacceptable_for_django_project(directory): print """\nDirectory %s is not acceptable for a Django project. Please use lower case characters, numbers and underscore. The first character cannot be a number.\n""" % os.path.basename(directory) return None return directory
def get_install_directory(force = False): """returns a directory where a new django app/project can be installed. If ``force`` is ``True`` - will permit using a directory with an existing django project. """ from askbot.deployment import messages where_to_deploy_msg = messages.WHERE_TO_DEPLOY_QUIT directory = raw_input(where_to_deploy_msg + ' ') directory = clean_directory(directory) if directory is None: return None if can_create_path(directory) == False: print messages.format_msg_dir_not_writable(directory) return None if os.path.exists(directory): if path_is_clean_for_django(directory): if has_existing_django_project(directory): if not force: print messages.CANNOT_OVERWRITE_DJANGO_PROJECT % \ {'directory': directory} return None else: print messages.format_msg_dir_unclean_django(directory) return None elif force == False: message = messages.format_msg_create(directory) should_create_new = console.choice_dialog( message, choices = ['yes','no'], invalid_phrase = messages.INVALID_INPUT ) if should_create_new == 'no': return None if not dir_name_acceptable(directory): print messages.format_msg_bad_dir_name(directory) return None return directory
def get_admin(seed_user_id = None): """requests admin with an optional seeded user id """ try: admin = api.get_admin(seed_user_id=seed_user_id) except models.User.DoesNotExist as e: raise CommandError(e) if admin.id != seed_user_id: if seed_user_id is None: prompt = """You have not provided user id for the moderator who to assign as the performer this operation, the default moderator is %s, id=%s. Will that work?""" % (admin.username, admin.id) else: prompt = """User with id=%s is not a moderator would you like to select default moderator %s, id=%d to run this operation?""" % (seed_user_id, admin.username, admin.id) choice = console.choice_dialog(prompt, choices = ('yes', 'no')) if choice == 'no': print('Canceled') sys.exit() return admin
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)
""" try: admin = api.get_admin(seed_user_id = seed_user_id) except models.User.DoesNotExist, e: raise CommandError(e) if admin.id != seed_user_id: if seed_user_id is None: prompt = """You have not provided user id for the moderator who to assign as the performer this operation, the default moderator is %s, id=%s. Will that work?""" % (admin.username, admin.id) else: prompt = """User with id=%s is not a moderator would you like to select default moderator %s, id=%d to run this operation?""" % (seed_user_id, admin.username, admin.id) choice = console.choice_dialog(prompt, choices = ('yes', 'no')) if choice == 'no': print 'Canceled' sys.exit() return admin def parse_tag_names(input): decoded_input = input.decode(sys.stdin.encoding) return set(decoded_input.strip().split(' ')) def format_tag_ids(tag_list): return ' '.join([str(tag.id) for tag in tag_list]) class Command(BaseCommand): "The command object itself"
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')
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)
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)
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')
def handle_noargs(self, **options): self.options = options self.verbosity = int(options.get("verbosity", 1)) self.interactive = options.get("interactive") # post a bunch of answers by admin now - that active_question is # posted by someone else if self.interactive: answer = choice_dialog("This command will DELETE ALL DATA in the current database, and will fill the database with test data. Are you absolutely sure you want to proceed?", choices = ("yes", "no", )) if answer != "yes": return translation.activate(django_settings.LANGUAGE_CODE) self.backup_settings() self.modify_settings()# saves time on running the command # Create Users users = self.create_users() # Create a bunch of questions and answers by a single user # to test pagination in the user profile active_question = self.create_questions(users[0:1]) # Create Questions, vote for questions by all other users active_question = self.create_questions(users) active_answer = self.create_answers(users[0:1], active_question) # Create Answers, vote for the answers, vote for the active question # vote for the active answer active_answer = self.create_answers(users, active_question) # Create Comments, vote for the active answer active_question_comment, active_answer_comment = self.create_comments( users, active_question, active_answer) # Edit the active question, answer and comments active_question.author.edit_question( question = active_question, title = TITLE_TEMPLATE % "EDITED", body_text = self.bad_stuff() + CONTENT_TEMPLATE, revision_comment = "EDITED", force = True ) self.print_if_verbose("User has edited the active question") active_answer.author.edit_answer( answer = active_answer, body_text = self.bad_stuff() + COMMENT_TEMPLATE, force = True ) self.print_if_verbose("User has edited the active answer") active_answer_comment.author.edit_comment( comment_post = active_answer_comment, body_text = self.bad_stuff() + ANSWER_TEMPLATE ) self.print_if_verbose("User has edited the active answer comment") active_question_comment.author.edit_comment( comment_post = active_question_comment, body_text = self.bad_stuff() + ANSWER_TEMPLATE ) self.print_if_verbose("User has edited the active question comment") # Accept best answer active_question.author.accept_best_answer( answer = active_answer, force = True, ) self.print_if_verbose("User has accepted a best answer") self.restore_settings() self.print_if_verbose("DONE")
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
def handle_noargs(self, **options): self.verbosity = int(options.get("verbosity", 1)) self.interactive = options.get("interactive") if self.interactive: problem = choice_dialog("This command will DELETE ALL DATA in the current database, and will fill the database with test data. Are you absolutely sure you want to proceed?", choices = ("yes", "no", )) if problem != "yes": return self.save_alert_settings() self.stop_alerts()# saves time on running the command # Create Users users = self.create_users() # Create Exercises, vote for exercises active_exercise = self.create_exercises(users) # Create Problems, vote for the problems, vote for the active exercise # vote for the active problem active_problem = self.create_problems(users, active_exercise) # Create Comments, vote for the active problem active_exercise_comment, active_problem_comment = self.create_comments( users, active_exercise, active_problem) # Edit the active exercise, problem and comments active_exercise.author.edit_exercise( exercise = active_exercise, title = TITLE_TEMPLATE % "EDITED", body_text = CONTENT_TEMPLATE, revision_comment = "EDITED", force = True ) self.print_if_verbose("User has edited the active exercise") active_problem.author.edit_problem( problem = active_problem, body_text = COMMENT_TEMPLATE, force = True ) self.print_if_verbose("User has edited the active problem") active_problem_comment.author.edit_comment( comment_post = active_problem_comment, body_text = PROBLEM_TEMPLATE ) self.print_if_verbose("User has edited the active problem comment") active_exercise_comment.author.edit_comment( comment_post = active_exercise_comment, body_text = PROBLEM_TEMPLATE ) self.print_if_verbose("User has edited the active exercise comment") # Accept best problem active_exercise.author.accept_best_problem( problem = active_problem, force = True, ) self.print_if_verbose("User has accepted a best problem") self.restore_saved_alert_settings() self.print_if_verbose("DONE")
def handle_noargs(self, **options): self.verbosity = int(options.get("verbosity", 1)) self.interactive = options.get("interactive") if self.interactive: problem = choice_dialog( "This command will DELETE ALL DATA in the current database, and will fill the database with test data. Are you absolutely sure you want to proceed?", choices=( "yes", "no", )) if problem != "yes": return self.save_alert_settings() self.stop_alerts() # saves time on running the command # Create Users users = self.create_users() # Create Exercises, vote for exercises active_exercise = self.create_exercises(users) # Create Problems, vote for the problems, vote for the active exercise # vote for the active problem active_problem = self.create_problems(users, active_exercise) # Create Comments, vote for the active problem active_exercise_comment, active_problem_comment = self.create_comments( users, active_exercise, active_problem) # Edit the active exercise, problem and comments active_exercise.author.edit_exercise(exercise=active_exercise, title=TITLE_TEMPLATE % "EDITED", body_text=CONTENT_TEMPLATE, revision_comment="EDITED", force=True) self.print_if_verbose("User has edited the active exercise") active_problem.author.edit_problem(problem=active_problem, body_text=COMMENT_TEMPLATE, force=True) self.print_if_verbose("User has edited the active problem") active_problem_comment.author.edit_comment( comment_post=active_problem_comment, body_text=PROBLEM_TEMPLATE) self.print_if_verbose("User has edited the active problem comment") active_exercise_comment.author.edit_comment( comment_post=active_exercise_comment, body_text=PROBLEM_TEMPLATE) self.print_if_verbose("User has edited the active exercise comment") # Accept best problem active_exercise.author.accept_best_problem( problem=active_problem, force=True, ) self.print_if_verbose("User has accepted a best problem") self.restore_saved_alert_settings() self.print_if_verbose("DONE")
def choice_dialog(self, prompt, choices=None, default=None): """Choice dialog, if necessary - preceded by the preamble""" if not self.preamble_printed: self.print_preamble() self.preamble_printed = True return console.choice_dialog(prompt, choices=choices, default=default)
def askbot_setup(): """basic deployment procedure asks user several questions, then either creates new deployment (in the case of new installation) or gives hints on how to add askbot to an existing Django project """ parser = OptionParser(usage = "%prog [options]") parser.add_option( "-v", "--verbose", dest = "verbosity", type = "int", default = 1, help = "verbosity level available values 0, 1, 2." ) parser.add_option( "-n", "--dir-name", dest = "dir_name", default = None, help = "Directory where you want to install." ) parser.add_option( '-e', '--db-engine', dest='database_engine', action='store', type='choice', choices=DATABASE_ENGINE_CHOICES, default=None, help='Database engine, type 1 for postgresql, 2 for sqlite, 3 for mysql' ) parser.add_option( "-d", "--db-name", dest = "database_name", default = None, help = "The database name" ) parser.add_option( "-u", "--db-user", dest = "database_user", default = None, help = "The database user" ) parser.add_option( "-p", "--db-password", dest = "database_password", default = None, help = "the database password" ) parser.add_option( "--domain", dest = "domain_name", default = None, help = "the domain name of the instance" ) parser.add_option( "--append-settings", dest = "local_settings", default = '', help = "Extra settings file to append custom settings" ) parser.add_option( "--force", dest="force", action='store_true', default=False, help = "Force overwrite settings.py file" ) try: options = parser.parse_args()[0] #ask users to give missing parameters #todo: make this more explicit here if options.verbosity >= 1: print messages.DEPLOY_PREAMBLE directory = path_utils.clean_directory(options.dir_name) while directory is None: directory = path_utils.get_install_directory(force=options.force) options.dir_name = directory if options.database_engine not in DATABASE_ENGINE_CHOICES: options.database_engine = console.choice_dialog( 'Please select database engine:\n1 - for postgresql, ' '2 - for sqlite, 3 - for mysql, 4 - oracle', choices=DATABASE_ENGINE_CHOICES ) options_dict = vars(options) if options.force is False: options_dict = collect_missing_options(options_dict) database_engine_codes = { '1': 'postgresql_psycopg2', '2': 'sqlite3', '3': 'mysql', '4': 'oracle' } database_engine = database_engine_codes[options.database_engine] options_dict['database_engine'] = database_engine deploy_askbot(options_dict) if database_engine == 'postgresql_psycopg2': try: import psycopg2 except ImportError: print '\nNEXT STEPS: install python binding for postgresql' print 'pip install psycopg2\n' elif database_engine == 'mysql': try: import _mysql except ImportError: print '\nNEXT STEP: install python binding for mysql' print 'pip install mysql-python\n' except KeyboardInterrupt: print "\n\nAborted." sys.exit(1)
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
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)
def askbot_setup(): """basic deployment procedure asks user several questions, then either creates new deployment (in the case of new installation) or gives hints on how to add askbot to an existing Django project """ #ask print messages.DEPLOY_PREAMBLE directory = None #directory where to put stuff create_new = False #create new django project or not where_to_deploy_msg = messages.WHERE_TO_DEPLOY while directory is None: directory = raw_input(where_to_deploy_msg + ' ') where_to_deploy_msg = messages.WHERE_TO_DEPLOY_QUIT directory = os.path.normpath(directory) directory = os.path.abspath(directory) if os.path.isfile(directory): print messages.CANT_INSTALL_INTO_FILE % {'path':directory} directory = None continue if path_utils.can_create_path(directory): if os.path.exists(directory): if path_utils.path_is_clean_for_django(directory): if path_utils.has_existing_django_project(directory): message = messages.SHOULD_ADD_APP_HERE % \ { 'path': directory } should_add_app = console.choice_dialog( message, choices = ['yes','no'], invalid_phrase = messages.INVALID_INPUT ) if should_add_app == 'yes': assert(create_new == False) if path_utils.dir_name_acceptable(directory): break else: print messages.format_msg_bad_dir_name(directory) directory = None continue else: directory = None continue else: assert(directory != None) if path_utils.dir_name_acceptable(directory): create_new = True break else: print messages.format_msg_bad_dir_name(directory) directory = None continue else: print messages.format_msg_dir_unclean_django(directory) directory = None continue else: message = messages.format_msg_create(directory) should_create_new = console.choice_dialog( message, choices = ['yes','no'], invalid_phrase = messages.INVALID_INPUT ) if should_create_new == 'yes': if path_utils.dir_name_acceptable(directory): create_new = True break else: print messages.format_msg_bad_dir_name(directory) directory = None continue else: directory = None continue else: print messages.format_msg_dir_not_writable(directory) directory = None continue help_file = path_utils.get_path_to_help_file() if create_new: path_utils.create_path(directory) path_utils.deploy_into(directory, new_project = True) print messages.HOW_TO_DEPLOY_NEW % {'help_file': help_file} else: path_utils.deploy_into(directory, new_project = False) print messages.HOW_TO_ADD_ASKBOT_TO_DJANGO % {'help_file': help_file}