def reject_suggestion(request, unit, suggid, **kwargs_): try: suggestion = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: raise Http404 # In order to be able to reject a suggestion, users have to either: # 1. Have `review` rights, or # 2. Be the author of the suggestion being rejected has_permission = ( check_permission('review', request) or (not request.user.is_anonymous() and request.user == suggestion.user)) if not has_permission: raise PermissionDenied( _('Insufficient rights to access review mode.')) review.get(Suggestion)( [suggestion], request.user).reject(QueryDict(request.body).get("comment")) json = { 'udbid': unit.id, 'sugid': suggid, 'user_score': request.user.public_score, } return JsonResponse(json)
def test_timeline_unit_with_suggestion_and_comment(store0, admin): suggestion = Suggestion.objects.filter( unit__store=store0, state__name="pending", unit__state=UNTRANSLATED).first() unit = suggestion.unit review.get(Suggestion)([suggestion], admin).accept() comment = 'This is a comment!' form = UnsecuredCommentForm(suggestion, admin, dict( comment=comment)) assert form.is_valid() form.save() suggestion.refresh_from_db() unit.refresh_from_db() timeline = Timeline(unit) groups = timeline.grouped_events(start=suggestion.review_time) assert len(groups) == 1 group = groups[0] assert len(group['events']) == 2 assert group['events'][0]['value'] == unit.target assert group['events'][0]['translation'] assert (group['events'][0]['description'] == _get_sugg_accepted_with_comment_desc(suggestion, comment)) submission = Submission.objects.get(field=SubmissionFields.STATE, unit=suggestion.unit, creation_time=suggestion.review_time) assert group['events'][1]['value'] == _get_state_changed_value(submission) assert group['via_upload'] is False assert group['datetime'] == suggestion.review_time assert group['user'].username == admin.username
def suggest(request, unit, **kwargs_): """Processes translation suggestions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit, request=request) unit_target = unit.target if form.is_valid(): target = form.cleaned_data["target_f"] if target and target != unit_target: unit = Unit.objects.get(id=unit.id) review.get(Suggestion)().add( unit, form.cleaned_data['target_f'], user=request.user) if not request.user.is_anonymous: json['user_score'] = request.user.public_score return JsonResponse(json) return JsonResponseBadRequest({'msg': _("Failed to process suggestion.")})
def test_contextmanager_update_tp_after_suggestion(tp0, store0, member, update_unit_test): unit = store0.units.first() sugg_review = review.get(Suggestion) with update_unit_test(SuggestionAddTest(unit)): with update_tp_after(tp0): sugg_text = str(unit.source_f).replace("U", "X") sugg1, created_ = review.get(Suggestion)().add( unit, sugg_text, user=member) with update_unit_test(SuggestionAcceptTest(unit)): with update_tp_after(tp0): sugg_review(suggestions=[sugg1], reviewer=member).accept() unit = store0.units.exclude(pk=unit.pk).first() with update_unit_test(SuggestionAddTest(unit)): with update_tp_after(tp0): sugg_text = str(unit.source_f).replace("U", "X") sugg1, created_ = review.get(Suggestion)().add( unit, sugg_text, user=member) with update_unit_test(SuggestionRejectTest(unit)): with update_tp_after(tp0): sugg_review(suggestions=[sugg1], reviewer=member).reject()
def test_refresh_scores_recalculate(capfd, store0, member): """Recalculate scores.""" # delete the 2 most prolific contribs to speed up unit = store0.units.filter(suggestion__state__name="pending").first() suggestion = unit.suggestion_set.filter(state__name="pending").first() member_score = member.score with keep_data(): review.get(suggestion.__class__)( [suggestion], reviewer=member).accept() member.refresh_from_db() assert member.score == member_score call_command('refresh_scores') member.refresh_from_db() assert member.score > member_score
def accept_suggestion(request, unit, suggid, **kwargs_): try: suggestion = unit.suggestion_set.get(id=suggid) except ObjectDoesNotExist: raise Http404 review.get(Suggestion)( [suggestion], request.user).accept(request.POST.get("comment")) json = { 'udbid': unit.id, 'sugid': suggid, 'user_score': request.user.public_score, 'newtargets': [target for target in unit.target.strings], 'checks': _get_critical_checks_snippet(request, unit), } return JsonResponse(json)
def test_timeline_view_unit_with_suggestion(client, request_users, system, admin, store0): # test with "state change" subission - apparently this is what is required # to get one suggestion = Suggestion.objects.filter( unit__store=store0, state=SuggestionStates.PENDING, unit__state=UNTRANSLATED).first() unit = suggestion.unit unit.state = FUZZY unit.save() review.get(Suggestion)([suggestion], admin).accept() _timeline_test( client, request_users, unit)
def test_accept_suggestion_update_wordcount(it_tutorial_po, system): """Tests that accepting a suggestion for an untranslated unit will change the wordcount stats of the unit's store. """ orig_translated = it_tutorial_po.data.translated_words suggestions = review.get(Suggestion)() untranslated_unit = it_tutorial_po.units[0] suggestion_text = 'foo bar baz' sugg, added = suggestions.add(untranslated_unit, suggestion_text) assert sugg is not None assert added assert len(untranslated_unit.get_suggestions()) == 1 assert untranslated_unit.state == UNTRANSLATED review.get(Suggestion)([sugg], system).accept() assert untranslated_unit.state == TRANSLATED assert it_tutorial_po.data.translated_words > orig_translated
def test_user_tp_score_update_translated(store0, member): # member translates another unit, by suggesting and # accepting own suggestion # score, suggested and translated increase suggestion_text = "made a suggestion!" suggestions = review.get(Suggestion) current_score = member.scores.get( tp=store0.translation_project, date=timezone.now().date()) old_score = current_score.score old_suggested = current_score.suggested old_translated = current_score.translated old_reviewed = current_score.reviewed unit = store0.units.filter(state=UNTRANSLATED)[0] sugg, added = suggestions().add( unit, suggestion_text, user=member) suggestions([sugg], member).accept() current_score.refresh_from_db() assert current_score.score > old_score assert ( current_score.suggested == old_suggested + unit.source_wordcount) assert current_score.reviewed == old_reviewed # this should be a wordcount but its some "paid" stuff # we need to change as i dont believe the value set here # is meaningful assert current_score.translated > old_translated
def test_accept_suggestion_changes_state(issue_2401_po, system): """Tests that accepting a suggestion will change the state of the unit.""" suggestions = review.get(Suggestion)() # First test with an untranslated unit unit = issue_2401_po.units[0] assert unit.state == UNTRANSLATED suggestion, created_ = suggestions.add(unit, "foo") assert unit.state == UNTRANSLATED review.get(Suggestion)([suggestion], system).accept() assert unit.state == TRANSLATED # Let's try with a translated unit now unit = issue_2401_po.units[1] assert unit.state == TRANSLATED suggestion, created_ = suggestions.add(unit, "bar") assert unit.state == TRANSLATED review.get(Suggestion)([suggestion], system).accept() assert unit.state == TRANSLATED # And finally a fuzzy unit unit = issue_2401_po.units[2] assert unit.state == FUZZY suggestion, created_ = suggestions.add(unit, "baz") assert unit.state == FUZZY review.get(Suggestion)([suggestion], system).accept() assert unit.state == TRANSLATED
def test_hash(store0): """Tests that target hash changes when suggestion is modified""" unit = store0.units[0] suggestions = review.get(Suggestion)() suggestion, created_ = suggestions.add(unit, "gras") first_hash = suggestion.target_hash suggestion.target = "gras++" second_hash = suggestion.target_hash assert first_hash != second_hash
def _make_evil_member_updates(store, evil_member): # evil_member makes following changes: # - rejects member's suggestion on unit # - changes unit # - adds another suggestion on unit # - accepts their own suggestion # - adds a comment on unit # - adds another unit member_suggestion = store.units[0].get_suggestions().first() evil_units = [ ("Hello, world", "Hello, world EVIL"), ("Goodbye, world", "Goodbye, world EVIL")] review.get(Suggestion)([member_suggestion], evil_member).reject() _create_submission_and_suggestion(store, evil_member, units=evil_units, suggestion="EVIL SUGGESTION") evil_suggestion = store.units[0].get_suggestions().first() review.get(Suggestion)([evil_suggestion], evil_member).accept() _create_comment_on_unit(store.units[0], evil_member, "EVIL COMMENT")
def _create_submission_and_suggestion(store, user, units=None, suggestion="SUGGESTION"): from pootle.core.delegate import review from pootle.core.models import Revision from pootle_store.models import Suggestion # Update store as user if units is None: units = [("Hello, world", "Hello, world UPDATED", False)] update_store( store, units, user=user, store_revision=Revision.get() + 1) # Add a suggestion unit = store.units[0] review.get(Suggestion)().add(unit, suggestion, user) return unit
def create_suggestion(self): suggestion_review = review.get(Suggestion)() return bool( suggestion_review.add( self.unit, self.newunit.target, self.update.user)[1] if self.update.resolve_conflict == POOTLE_WINS else suggestion_review.add( self.unit, self.original.target, self.original.submitter)[1])
def test_timeline_translated_unit_with_suggestion(store0, admin): suggestion = Suggestion.objects.filter( unit__store=store0, state__name="pending", unit__state=TRANSLATED).first() unit = suggestion.unit review.get(Suggestion)([suggestion], admin).accept() suggestion.refresh_from_db() unit.refresh_from_db() timeline = Timeline(unit) groups = timeline.grouped_events(start=suggestion.review_time) assert len(groups) == 1 group = groups[0] assert len(group['events']) == 1 assert group['events'][0]['value'] == unit.target assert group['events'][0]['translation'] assert (group['events'][0]['description'] == _get_sugg_accepted_desc(suggestion)) assert group['via_upload'] is False assert group['datetime'] == suggestion.review_time assert group['user'].username == admin.username
def test_add_suggestion(store0, system): """Tests adding new suggestions to units.""" untranslated_unit = store0.units.filter(state=UNTRANSLATED)[0] translated_unit = store0.units.filter(state=TRANSLATED)[0] suggestion_text = 'foo bar baz' initial_suggestions = len(untranslated_unit.get_suggestions()) suggestions = review.get(Suggestion)() # Empty suggestion is not recorded sugg, added = suggestions.add(untranslated_unit, "") assert sugg is None assert not added # Existing translation can't be added as a suggestion sugg, added = suggestions.add(translated_unit, translated_unit.target) assert sugg is None assert not added # Add new suggestion sugg, added = suggestions.add(untranslated_unit, suggestion_text) assert sugg is not None assert added assert len(untranslated_unit.get_suggestions()) == initial_suggestions + 1 # Already-suggested text can't be suggested again sugg, added = suggestions.add(untranslated_unit, suggestion_text) assert sugg is not None assert not added assert len(untranslated_unit.get_suggestions()) == initial_suggestions + 1 # Removing a suggestion should allow suggesting the same text again review.get(Suggestion)([sugg], system).reject() assert len(untranslated_unit.get_suggestions()) == initial_suggestions sugg, added = suggestions.add(untranslated_unit, suggestion_text) assert sugg is not None assert added assert len(untranslated_unit.get_suggestions()) == initial_suggestions + 1
def suggest(request, unit, **kwargs_): """Processes translation suggestions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit, request=request) if form.is_valid(): if form.cleaned_data.get("target_updated"): # TODO: Review if this hackish method is still necessary # HACKISH: django 1.2 stupidly modifies instance on model form # validation, reload unit from db unit = Unit.objects.get(id=unit.id) review.get(Suggestion)().add( unit, form.cleaned_data['target_f'], user=request.user, similarity=form.cleaned_data['similarity'], mt_similarity=form.cleaned_data['mt_similarity']) if not request.user.is_anonymous: json['user_score'] = request.user.public_score return JsonResponse(json) return JsonResponseBadRequest({'msg': _("Failed to process suggestion.")})
def test_timeline_view_unit_with_suggestion_and_comment(client, request_users, system, admin, store0): # test with "state change" subission - apparently this is what is required # to get one suggestion = Suggestion.objects.filter( unit__store=store0, state=SuggestionStates.PENDING, unit__state=UNTRANSLATED).first() unit = suggestion.unit unit.state = FUZZY unit.save() review.get(Suggestion)([suggestion], admin).accept() form = UnsecuredCommentForm(suggestion, dict( comment='This is a comment!', user=admin, )) if form.is_valid(): form.save() _timeline_test( client, request_users, unit)
def test_data_tp_util_suggestion_count(tp0, member): units = Unit.objects.filter( state__gt=OBSOLETE, store__translation_project=tp0) suggestions = Suggestion.objects.filter( unit__store__translation_project=tp0, unit__state__gt=OBSOLETE, state__name="pending") original_suggestion_count = suggestions.count() update_data = tp0.data_tool.updater.get_store_data() tp0.data.refresh_from_db() assert( update_data["pending_suggestions"] == tp0.data.pending_suggestions == tp0.data_tool.updater.get_pending_suggestions() == original_suggestion_count) unit = units.filter( state__gt=OBSOLETE, suggestion__state__name="pending").first() unit_suggestion_count = unit.suggestion_set.filter( state__name="pending").count() unit_suggestion_count = unit.suggestion_set.filter( state__name="pending").count() sugg, added = review.get(Suggestion)().add( unit, "Another suggestion for %s" % (unit.target or unit.source), user=member) # unit now has an extra suggestion assert ( unit.suggestion_set.filter(state__name="pending").count() == unit_suggestion_count + 1) update_data = tp0.data_tool.updater.get_store_data() tp0.data.refresh_from_db() assert( update_data["pending_suggestions"] == tp0.data.pending_suggestions == tp0.data_tool.updater.get_pending_suggestions() == original_suggestion_count + 1) tp0.data_tool.update(pending_suggestions=1000000) update_data = tp0.data_tool.updater.get_store_data() assert( tp0.data.pending_suggestions == 1000000) assert( update_data["pending_suggestions"] == tp0.data_tool.updater.get_pending_suggestions() == original_suggestion_count + 1)
def test_user_tp_score_update_suggestions(store0, member, member2): unit = store0.units.filter(state=UNTRANSLATED)[0] suggestions = review.get(Suggestion) suggestion_text = "made a suggestion!" # member adds a suggestion # score and sugg increase current_score = member.scores.get( tp=store0.translation_project, date=timezone.now().date()) old_suggested = current_score.suggested old_score = current_score.score old_suggested = current_score.suggested old_translated = current_score.translated old_reviewed = current_score.reviewed sugg, added = suggestions().add( unit, suggestion_text, user=member) current_score = member.scores.get( tp=store0.translation_project, date=timezone.now().date()) assert current_score.score == old_score assert ( current_score.suggested == old_suggested + unit.source_wordcount) assert current_score.translated == old_translated assert current_score.reviewed == old_reviewed # member2 reviews members suggestion # score and review increase m2_score = member2.scores.get( tp=store0.translation_project, date=timezone.now().date()) old_m2_score = m2_score.score old_m2_suggested = m2_score.suggested old_m2_translated = m2_score.translated old_m2_reviewed = m2_score.reviewed suggestions([sugg], member2).accept() m2_score = member2.scores.get( tp=store0.translation_project, date=timezone.now().date()) assert m2_score.score > old_m2_score assert ( m2_score.reviewed == old_m2_reviewed + unit.source_wordcount) assert m2_score.suggested == old_m2_suggested assert m2_score.translated == old_m2_translated
def test_accept_suggestion_no_update(store0, member): """Tests adding new suggestions to units.""" unit = store0.units.filter(suggestion__state__name="pending").first() original = unit._frozen last_sub_pk = ( unit.submission_set.order_by( "-pk").values_list("id", flat=True).first() or 0) suggestion = unit.suggestion_set.filter(state__name="pending").last() suggestion_review = review.get(Suggestion)([suggestion]) suggestion_review.accept(update_unit=False) assert not unit.updated unit.refresh_from_db() assert not unit.changed assert unit.target == original.target assert unit.revision == original.revision new_subs = unit.submission_set.filter(id__gt=last_sub_pk) assert new_subs.count() == 0
def test_user_tp_score_update_translated(store0, member, member2): # member translates another unit, by suggesting and # accepting own suggestion # score, suggested and translated increase suggestion_text = "made a suggestion!" suggestions = review.get(Suggestion) current_score = member.scores.get( tp=store0.translation_project, date=timezone.now().date()) old_score = round(current_score.score, 2) old_suggested = current_score.suggested old_translated = current_score.translated old_reviewed = current_score.reviewed m2_score = member2.scores.get( tp=store0.translation_project, date=timezone.now().date()) m2_old_score = round(m2_score.score, 2) m2_suggested = m2_score.suggested m2_translated = m2_score.translated m2_reviewed = m2_score.reviewed unit = store0.units.filter(state=UNTRANSLATED)[0] sugg, added = suggestions().add( unit, suggestion_text, user=member) suggestions([sugg], member2).accept() current_score = member.scores.get( tp=store0.translation_project, date=timezone.now().date()) assert round(current_score.score, 2) > old_score assert current_score.reviewed == old_reviewed assert ( current_score.suggested == old_suggested + unit.unit_source.source_wordcount) assert ( current_score.translated == old_translated + unit.unit_source.source_wordcount) m2_score = member2.scores.get( tp=store0.translation_project, date=timezone.now().date()) assert round(m2_score.score, 2) > m2_old_score assert m2_score.suggested == m2_suggested assert m2_score.translated == m2_translated assert ( m2_score.reviewed == m2_reviewed + unit.unit_source.source_wordcount)
def test_data_store_util_suggestion_count(store0, member): suggestions = Suggestion.objects.filter( unit__store=store0, unit__state__gt=OBSOLETE, state=SuggestionStates.PENDING) original_suggestion_count = suggestions.count() update_data = store0.data_tool.updater.get_store_data() assert( update_data["pending_suggestions"] == store0.data.pending_suggestions == store0.data_tool.updater.get_pending_suggestions() == original_suggestion_count) unit = store0.units.filter( state__gt=OBSOLETE, suggestion__state=SuggestionStates.PENDING).first() unit_suggestion_count = unit.suggestion_set.filter( state=SuggestionStates.PENDING).count() sugg, added = review.get(Suggestion)().add( unit, "Another suggestion for %s" % (unit.target or unit.source), user=member) # unit now has an extra suggestion assert ( unit.suggestion_set.filter(state=SuggestionStates.PENDING).count() == unit_suggestion_count + 1) store0.data.refresh_from_db() update_data = store0.data_tool.updater.get_store_data() assert( update_data["pending_suggestions"] == store0.data.pending_suggestions == store0.data_tool.updater.get_pending_suggestions() == original_suggestion_count + 1) store0.data_tool.update(pending_suggestions=1000000) update_data = store0.data_tool.updater.get_store_data() assert( store0.data.pending_suggestions == 1000000) assert( update_data["pending_suggestions"] == store0.data_tool.updater.get_pending_suggestions() == original_suggestion_count + 1)
def test_accept_suggestion_with_comment_email_escaped(store0, mailoutbox, member2): """Tests that email sent on accept suggestions with comment is escaped.""" unit = store0.units[0] suggestion_review_cls = review.get(Suggestion) review_instance = suggestion_review_cls() suggestion, created_ = review_instance.add(unit, "gras", user=member2) comment = "Very nice" suggestion_review_cls([suggestion]).accept(comment=comment) assert len(mailoutbox) == 1 message = mailoutbox[0] assert comment in message.body suggestion, created_ = review_instance.add(unit, "gras++", user=member2) comment = "Good job not translating <tag> tags" suggestion_review_cls([suggestion]).accept(comment=comment) assert len(mailoutbox) == 2 message = mailoutbox[1] assert comment not in message.body assert escape(comment) in message.body
def test_reject_suggestion_with_comment_email_escaped(store0, mailoutbox, member2): """Tests that email sent on reject suggestions with comment is escaped.""" unit = store0.units[0] suggestion_review_cls = review.get(Suggestion) review_instance = suggestion_review_cls() suggestion, created_ = review_instance.add(unit, "gras", user=member2) comment = "It is wrong" suggestion_review_cls([suggestion]).reject(comment=comment) assert len(mailoutbox) == 1 message = mailoutbox[0] assert comment in message.body suggestion, created_ = review_instance.add(unit, "gras++", user=member2) comment = "The <tag> must not be translated" suggestion_review_cls([suggestion]).reject(comment=comment) assert len(mailoutbox) == 2 message = mailoutbox[1] assert comment not in message.body assert escape(comment) in message.body
def test_user_tp_score_update_rejects(store0, member, member2): # member makes another suggestion then member2 rejects suggestion_text = "made a suggestion!" suggestions = review.get(Suggestion) current_score = member.scores.get( tp=store0.translation_project, date=localdate()) old_score = round(current_score.score, 2) old_suggested = current_score.suggested old_translated = current_score.translated old_reviewed = current_score.reviewed m2_score = member2.scores.get( tp=store0.translation_project, date=localdate()) m2_old_score = round(m2_score.score, 2) m2_suggested = m2_score.suggested m2_translated = m2_score.translated m2_reviewed = m2_score.reviewed unit = store0.units.filter(state=UNTRANSLATED)[0] sugg, added = suggestions().add( unit, suggestion_text, user=member) suggestions([sugg], member2).reject() current_score = member.scores.get( tp=store0.translation_project, date=localdate()) assert round(current_score.score, 2) == old_score assert current_score.reviewed == old_reviewed assert current_score.translated == old_translated assert ( current_score.suggested == old_suggested + unit.unit_source.source_wordcount) m2_score = member2.scores.get( tp=store0.translation_project, date=localdate()) assert round(m2_score.score, 2) > m2_old_score assert m2_score.suggested == m2_suggested assert m2_score.translated == m2_translated assert ( m2_score.reviewed == m2_reviewed + unit.unit_source.source_wordcount)
def test_user_tp_score_update_rejects(store0, member): # member makes another suggestion then rejects # only suggested increases suggestion_text = "made a suggestion!" suggestions = review.get(Suggestion) current_score = member.scores.get( tp=store0.translation_project, date=timezone.now().date()) old_score = current_score.score old_suggested = current_score.suggested old_translated = current_score.translated old_reviewed = current_score.reviewed unit = store0.units.filter(state=UNTRANSLATED)[0] sugg, added = suggestions().add( unit, suggestion_text, user=member) suggestions([sugg], member).reject() current_score.refresh_from_db() assert ( current_score.suggested == old_suggested + unit.source_wordcount) assert current_score.score == old_score assert current_score.translated == old_translated assert current_score.reviewed == old_reviewed
def suggestions_review(self): if not self.is_valid(): return return review.get(Suggestion)(self.suggestions_to_save, self.user)
def _add_submissions(self, unit, created): from pootle.core.delegate import review from pootle_statistics.models import SubmissionTypes from pootle_store.constants import UNTRANSLATED, FUZZY, OBSOLETE from pootle_store.models import Suggestion, Unit from django.contrib.auth import get_user_model from django.utils import timezone original_state = unit.state unit.created = created User = get_user_model() admin = User.objects.get(username="******") member = User.objects.get(username="******") member2 = User.objects.get(username="******") first_modified = created + relativedelta(months=unit.index, days=10) # add suggestion at first_modified suggestion_review = review.get(Suggestion) suggestion, created_ = suggestion_review().add( unit, "Suggestion for %s" % (unit.target or unit.source), user=member, touch=False) self._update_submission_times(unit, first_modified, created) # accept the suggestion 7 days later if not untranslated next_time = first_modified + timedelta(days=7) if original_state == UNTRANSLATED: suggestion_review([suggestion], reviewer=admin).reject() else: suggestion_review([suggestion], reviewer=admin).accept() Unit.objects.filter(pk=unit.pk).update( submitted_on=next_time, mtime=next_time) self._update_submission_times( unit, next_time, first_modified) # add another suggestion as different user 7 days later suggestion2_, created_ = suggestion_review().add( unit, "Suggestion 2 for %s" % (unit.target or unit.source), user=member2, touch=False) self._update_submission_times( unit, first_modified + timedelta(days=14), next_time) # mark FUZZY if original_state == FUZZY: unit.markfuzzy() # mark OBSOLETE elif original_state == OBSOLETE: unit.makeobsolete() elif unit.target: # Re-edit units with translations, adding some submissions # of SubmissionTypes.EDIT_TYPES old_target = unit.target old_state = unit.state current_time = timezone.now() - timedelta(days=14) unit.target_f = "Updated %s" % old_target unit.store.record_submissions( unit, old_target, old_state, current_time, member, SubmissionTypes.NORMAL, target_updated=True) unit.save(target_updated=True)
def _add_submissions(self, unit, created, admin, member, member2): from pootle.core.delegate import review from pootle_store.constants import UNTRANSLATED, FUZZY, OBSOLETE from pootle_store.models import Suggestion, Unit, UnitChange from django.utils import timezone original_state = unit.state unit.created = created first_modified = created + relativedelta(months=unit.index, days=10) # add suggestion at first_modified suggestion_review = review.get(Suggestion) suggestion, created_ = suggestion_review().add( unit, "Suggestion for %s" % (unit.target or unit.source), user=member) self._update_submission_times(unit, first_modified, created) # accept the suggestion 7 days later if not untranslated next_time = first_modified + timedelta(days=7) if original_state == UNTRANSLATED: suggestion_review([suggestion], reviewer=admin).reject() else: Unit.objects.filter(pk=unit.pk).update(mtime=next_time) UnitChange.objects.filter( unit_id=unit.pk).update( reviewed_on=next_time, reviewed_by=admin, submitted_on=next_time) suggestion_review([suggestion], reviewer=admin).accept() self._update_submission_times( unit, next_time, first_modified) # add another suggestion as different user 7 days later suggestion2_, created_ = suggestion_review().add( unit, "Suggestion 2 for %s" % (unit.target or unit.source), user=member2) self._update_submission_times( unit, first_modified + timedelta(days=14), next_time) # mark FUZZY if original_state == FUZZY: unit.markfuzzy() # mark OBSOLETE elif original_state == OBSOLETE: unit.makeobsolete() elif unit.target: # Re-edit units with translations, adding some submissions # of SubmissionTypes.EDIT_TYPES old_target = unit.target current_time = timezone.now() - timedelta(days=14) unit.__class__.objects.filter(id=unit.id).update( target_f="Updated %s" % old_target, mtime=current_time) unit.change.save()
def suggestion_review(self): return review.get( self.target_object.__class__)([self.target_object], self.request_user, review_type=self.review_type)
def test_comparable_unit_timelime_log(member, store0): assert comparable_event.get(UnitTimelineLog) == ComparableLogEvent start = timezone.now().replace(microsecond=0) unit = store0.units.filter(state=TRANSLATED).first() unit.target += 'UPDATED IN TEST' unit.save(user=member) unit = store0.units.filter(state=TRANSLATED).first() unit.target += 'UPDATED IN TEST AGAIN' unit.save(user=member) unit_log = UnitTimelineLog(unit) event1, event2 = [ ComparableLogEvent(x) for x in unit_log.get_events(users=[member.id], start=start) ] assert (event1 < event2) == (event1.revision < event2.revision) assert (event2 < event1) == (event2.revision < event1.revision) unit = store0.units.filter(state=UNTRANSLATED).first() sugg1, created_ = review.get(Suggestion)().add(unit, unit.source_f + 'SUGGESTION', user=member) sugg2, created_ = review.get(Suggestion)().add(unit, unit.source_f + 'SUGGESTION AGAIN', user=member) unit_log = UnitTimelineLog(unit) Suggestion.objects.filter(id=sugg2.id).update( creation_time=sugg1.creation_time + timedelta(seconds=1)) event1, event2 = [ ComparableLogEvent(x) for x in unit_log.get_events(users=[member.id], start=start) ] assert (event1 < event2) == (event1.timestamp < event2.timestamp) assert (event2 < event1) == (event2.timestamp < event1.timestamp) Suggestion.objects.filter(id=sugg2.id).update( creation_time=sugg1.creation_time) event1, event2 = [ ComparableLogEvent(x) for x in unit_log.get_events(users=[member.id], start=start) ] assert (event1 < event2) == (event1.value.pk < event2.value.pk) assert (event2 < event1) == (event2.value.pk < event1.value.pk) Suggestion.objects.filter(id=sugg2.id).update(creation_time=None) sugg2 = Suggestion.objects.get(id=sugg2.id) event1 = [ ComparableLogEvent(x) for x in unit_log.get_events(users=[member.id], start=start) ][0] event2 = ComparableLogEvent( unit_log.event(sugg2.unit, sugg2.user, sugg2.creation_time, "suggestion_created", sugg2)) assert event2 < event1 assert not (event1 < event2) unit = store0.units.filter(state=UNTRANSLATED)[0] unit.target = 'Unit Target' unit.save() unit_log = UnitTimelineLog(unit) event1, event2 = [ ComparableLogEvent(x) for x in unit_log.get_submission_events() ] assert (event1 < event2) == (ACTION_ORDER[event1.action] < ACTION_ORDER[event2.action]) assert (event2 < event1) == (ACTION_ORDER[event2.action] < ACTION_ORDER[event1.action]) assert not (event1 < event1) and not (event1 > event1)
def test_timeline_groups(store0, admin, member, member2, system): expected = [] # 8 - unit_created unit = store0.addunit(store0.UnitClass(source="Foo"), user=system) unit.refresh_from_db() current_time = unit.creation_time.replace(microsecond=0) no_microseconds = (unit.creation_time == current_time) if no_microseconds: Unit.objects.filter(id=unit.id).update(creation_time=current_time) unit.refresh_from_db() expected[:0] = [(set(['unit_created']), _format_dt(unit.creation_time, no_microseconds), system)] # 7 - suggestion_created suggestion_0, __ = review.get(Suggestion)().add(unit, "Suggestion for Foo", user=member) if no_microseconds: current_time += timedelta(seconds=1) Suggestion.objects.filter(id=suggestion_0.id).update( creation_time=current_time) suggestion_0.refresh_from_db() expected[:0] = [(set(['suggestion_created']), _format_dt(suggestion_0.creation_time, no_microseconds), member)] # 6 - suggestion_created suggestion_1, __ = review.get(Suggestion)().add( unit, "Another suggestion for Foo", user=member2) if no_microseconds: current_time += timedelta(seconds=1) Suggestion.objects.filter(id=suggestion_1.id).update( creation_time=current_time) suggestion_1.refresh_from_db() expected[:0] = [(set(['suggestion_created']), _format_dt(suggestion_1.creation_time, no_microseconds), member2)] # 5 - comment_updated unit.translator_comment = "This is a comment!" unit.save(user=member) submission = _latest_submission(unit, 1)[0] if no_microseconds: current_time += timedelta(seconds=1) Submission.objects.filter(id=submission.id).update( creation_time=current_time) submission.refresh_from_db() unit.refresh_from_db() expected[:0] = [(set(['comment_updated']), _format_dt(submission.creation_time, no_microseconds), member)] # 4 - suggestion_accepted, target_updated, state_changed review.get(Suggestion)([suggestion_0], admin).accept() if no_microseconds: current_time += timedelta(seconds=1) Suggestion.objects.filter(id=suggestion_0.id).update( review_time=current_time) Submission.objects.filter(suggestion_id=suggestion_0.id).update( creation_time=current_time) suggestion_0.refresh_from_db() unit.refresh_from_db() expected[:0] = [ (set(['suggestion_accepted', 'target_updated', 'state_changed']), _format_dt(suggestion_0.review_time, no_microseconds), admin) ] # 3 - target_updated unit.target = "Overwritten translation for Foo" unit.save(user=member2) submission = _latest_submission(unit, 1)[0] if no_microseconds: current_time += timedelta(seconds=1) Submission.objects.filter(id=submission.id).update( creation_time=current_time) submission.refresh_from_db() unit.refresh_from_db() expected[:0] = [(set(['target_updated']), _format_dt(submission.creation_time, no_microseconds), member2)] # 2 - target_updated, state_changed unit.target = "" unit.save(user=admin) submissions = _latest_submission(unit, 2) if no_microseconds: current_time += timedelta(seconds=1) Submission.objects.filter(id__in=[x.id for x in submissions]).update( creation_time=current_time) for sub in submissions: sub.refresh_from_db() unit.refresh_from_db() expected[:0] = [(set(['target_updated', 'state_changed']), _format_dt(submissions[0].creation_time, no_microseconds), admin)] # 1 - suggestion_rejected review.get(Suggestion)([suggestion_1], admin).reject() if no_microseconds: current_time += timedelta(seconds=1) Suggestion.objects.filter(id=suggestion_1.id).update( review_time=current_time) suggestion_1.refresh_from_db() expected[:0] = [(set(['suggestion_rejected']), _format_dt(suggestion_1.review_time, no_microseconds), admin)] # 0 - comment_updated unit.translator_comment = "" unit.save(user=admin) submission = _latest_submission(unit, 1)[0] if no_microseconds: current_time += timedelta(seconds=1) Submission.objects.filter(id=submission.id).update( creation_time=current_time) submission.refresh_from_db() unit.refresh_from_db() expected[:0] = [(set(['comment_updated']), _format_dt(submission.creation_time, no_microseconds), admin)] log = UnitTimelineLog(unit) grouped_events_class = grouped_events.get(log.__class__) assert grouped_events_class == GroupedEvents groups = [list(x) for _j, x in grouped_events_class(log).grouped_events()] result = [(set([y.action for y in x]), _format_dt(x[0].timestamp, no_microseconds), _get_group_user(x)) for x in groups] assert expected == result
def _add_submissions(self, unit, created): from pootle.core.delegate import review from pootle_store.constants import UNTRANSLATED, FUZZY, OBSOLETE from pootle_store.models import Suggestion, Unit, UnitChange from django.contrib.auth import get_user_model from django.utils import timezone original_state = unit.state unit.created = created User = get_user_model() admin = User.objects.get(username="******") member = User.objects.get(username="******") member2 = User.objects.get(username="******") first_modified = created + relativedelta(months=unit.index, days=10) # add suggestion at first_modified suggestion_review = review.get(Suggestion) suggestion, created_ = suggestion_review().add( unit, "Suggestion for %s" % (unit.target or unit.source), user=member) self._update_submission_times(unit, first_modified, created) # accept the suggestion 7 days later if not untranslated next_time = first_modified + timedelta(days=7) if original_state == UNTRANSLATED: suggestion_review([suggestion], reviewer=admin).reject() else: Unit.objects.filter(pk=unit.pk).update(mtime=next_time) UnitChange.objects.filter(unit_id=unit.pk).update( reviewed_on=next_time, reviewed_by=admin, submitted_on=next_time) suggestion_review([suggestion], reviewer=admin).accept() self._update_submission_times(unit, next_time, first_modified) # add another suggestion as different user 7 days later suggestion2_, created_ = suggestion_review().add( unit, "Suggestion 2 for %s" % (unit.target or unit.source), user=member2) self._update_submission_times(unit, first_modified + timedelta(days=14), next_time) # mark FUZZY if original_state == FUZZY: unit.markfuzzy() # mark OBSOLETE elif original_state == OBSOLETE: unit.makeobsolete() elif unit.target: # Re-edit units with translations, adding some submissions # of SubmissionTypes.EDIT_TYPES old_target = unit.target current_time = timezone.now() - timedelta(days=14) unit.__class__.objects.filter(id=unit.id).update( target_f="Updated %s" % old_target, mtime=current_time) unit.change.save()
def submit(request, unit, **kwargs_): """Processes translation submissions and stores them in the database. :return: An object in JSON notation that contains the previous and last units for the unit next to unit ``uid``. """ json = {} translation_project = request.translation_project language = translation_project.language if unit.hasplural(): snplurals = len(unit.source.strings) else: snplurals = None # Store current time so that it is the same for all submissions current_time = timezone.now() form_class = unit_form_factory(language, snplurals, request) form = form_class(request.POST, instance=unit, request=request) if form.is_valid(): suggestion = form.cleaned_data['suggestion'] if suggestion: review.get(Suggestion)([suggestion], request.user).accept() if form.cleaned_data['comment']: kwargs = dict( comment=form.cleaned_data['comment'], user=request.user, ) comment_form = UnsecuredCommentForm(suggestion, kwargs) if comment_form.is_valid(): comment_form.save() if form.updated_fields: for field, old_value, new_value in form.updated_fields: if field == SubmissionFields.TARGET and suggestion: old_value = str(suggestion.target_f) sub = Submission( creation_time=current_time, translation_project=translation_project, submitter=request.user, unit=unit, store=unit.store, field=field, type=SubmissionTypes.NORMAL, old_value=old_value, new_value=new_value, similarity=form.cleaned_data['similarity'], mt_similarity=form.cleaned_data['mt_similarity'], ) sub.save() # Update current unit instance's attributes # important to set these attributes after saving Submission # because we need to access the unit's state before it was saved if SubmissionFields.TARGET in (f[0] for f in form.updated_fields): form.instance.submitted_by = request.user form.instance.submitted_on = current_time form.instance.reviewed_by = None form.instance.reviewed_on = None form.instance._log_user = request.user form.save() json['checks'] = _get_critical_checks_snippet(request, unit) json['user_score'] = request.user.public_score json['newtargets'] = [target for target in form.instance.target.strings] return JsonResponse(json) return JsonResponseBadRequest({'msg': _("Failed to process submission.")})
def test_log_get_suggestions(member, store0): suggestions = Suggestion.objects.all() sugg_start, sugg_end = _get_mid_times(suggestions) sugg_log = Log() sugg_events = sugg_log.get_suggestion_events() assert type(sugg_events).__name__ == "generator" user_time_suggestions = ( (sugg_log.filter_users(sugg_log.suggestions, [member], field="user_id") & sugg_log.filter_timestamps( sugg_log.suggestions, start=sugg_start, end=sugg_end)) | (sugg_log.filter_users(sugg_log.suggestions, [member], field="reviewer_id") & sugg_log.filter_timestamps(sugg_log.suggestions, start=sugg_start, end=sugg_end, field="review_time"))) assert user_time_suggestions pending = suggestions.filter(creation_time__gte=sugg_start, creation_time__lt=sugg_end, state__name="pending").first() review.get(Suggestion)([pending], member).accept() pending = suggestions.filter(creation_time__gte=sugg_start, creation_time__lt=sugg_end, state__name="pending").first() review.get(Suggestion)([pending], member).reject() pending.review_time = sugg_start pending.save() expected = {} for suggestion in user_time_suggestions.all(): add_event = ((suggestion.creation_time >= sugg_start) and (suggestion.creation_time < sugg_end) and (suggestion.user == member)) review_event = ((suggestion.review_time >= sugg_start) and (suggestion.review_time < sugg_end) and (suggestion.reviewer == member)) expected[suggestion.id] = {} if add_event: expected[suggestion.id]["suggestion_created"] = (sugg_log.event( suggestion.unit, suggestion.user, suggestion.creation_time, "suggestion_created", suggestion)) if review_event: event_name = ("suggestion_accepted" if suggestion.state.name == "accepted" else "suggestion_rejected") expected[suggestion.id][event_name] = (sugg_log.event( suggestion.unit, suggestion.reviewer, suggestion.review_time, event_name, suggestion)) result = sugg_log.get_suggestion_events(start=sugg_start, end=sugg_end, users=[member.id]) for event in result: assert isinstance(event, sugg_log.event) sugg_review = expected[event.value.pk][event.action] assert event.unit == sugg_review.unit assert event.action in [ "suggestion_created", "suggestion_accepted", "suggestion_rejected" ] assert event.user == (sugg_review.value.user if event.action == "suggestion_created" else sugg_review.value.reviewer) assert event.timestamp == (sugg_review.value.creation_time if event.action == "suggestion_created" else sugg_review.value.review_time) assert event.value == sugg_review.value
def test_comparable_log(member, store0, store_po): assert comparable_event.get(Log) == ComparableLogEvent start = timezone.now().replace(microsecond=0) unit = store0.units.filter(state=TRANSLATED).first() unit.target += 'UPDATED IN TEST' unit.save(user=member) unit = store0.units.filter(state=TRANSLATED).first() unit.target += 'UPDATED IN TEST AGAIN' unit.save(user=member) unit_log = log.get(unit.__class__)(unit) event1, event2 = [ ComparableLogEvent(x) for x in unit_log.get_events(users=[member.id], start=start) ] assert (event1 < event2) == (event1.revision < event2.revision) assert (event2 < event1) == (event2.revision < event1.revision) unit = store0.units.filter(state=UNTRANSLATED).first() sugg1, created_ = review.get(Suggestion)().add(unit, unit.source_f + 'SUGGESTION', user=member) sugg2, created_ = review.get(Suggestion)().add(unit, unit.source_f + 'SUGGESTION AGAIN', user=member) Suggestion.objects.filter(id=sugg2.id).update( creation_time=sugg1.creation_time) unit_log = log.get(unit.__class__)(unit) event1, event2 = [ ComparableLogEvent(x) for x in unit_log.get_events(users=[member.id], start=start) ] assert (event1 < event2) == (event1.value.pk < event2.value.pk) assert (event2 < event1) == (event2.value.pk < event1.value.pk) Suggestion.objects.filter(id=sugg2.id).update(creation_time=None) sugg2 = Suggestion.objects.get(id=sugg2.id) event1 = [ ComparableLogEvent(x) for x in unit_log.get_events(users=[member.id], start=start) ][0] event2 = ComparableLogEvent( unit_log.event(sugg2.unit, sugg2.user, sugg2.creation_time, "suggestion_created", sugg2)) assert event2 < event1 assert not (event1 < event2) units = [ ('Unit 0 Source', 'Unit 0 Target', False), ('Unit 1 Source', '', False), ] store_po.update(create_store(units=units)) unit1, unit2 = store_po.units unit2.__class__.objects.filter(id=unit2.id).update( creation_time=unit1.creation_time) store_log = log.get(store_po.__class__)(store_po) event1, event2 = [ComparableLogEvent(x) for x in store_log.get_events()] assert (event1 < event2) == (event1.unit.id < event2.unit.id) assert (event2 < event1) == (event2.unit.id < event1.unit.id) creation_time = unit1.creation_time + timedelta(seconds=1) unit2.__class__.objects.filter(id=unit2.id).update( creation_time=creation_time) event1, event2 = [ComparableLogEvent(x) for x in store_log.get_events()] assert (event1 < event2) == (event1.timestamp < event2.timestamp) assert (event2 < event1) == (event2.timestamp < event1.timestamp) unit = store_po.units.filter(state=UNTRANSLATED)[0] unit.target = 'Unit 1 Target' unit.save() unit_log = log.get(unit.__class__)(unit) event1, event2 = [ ComparableLogEvent(x) for x in unit_log.get_submission_events() ] assert not (event1 < event2) and not (event2 < event1)
def save_unit(self): user = self.request_user review.get(Suggestion)().add(self.unit, self.cleaned_data["target_f"], user=user)