def flip_artwork_flag(request, revision_id=None): """ flips the status in regard to variants with different cover artwork """ cover = get_object_or_404(CoverRevision, id=revision_id) changeset = cover.changeset if request.user != changeset.approver: return render_error(request, 'The variant artwork status may only be changed by the approver.') story = list(changeset.storyrevisions.all()) if len(story) == 1: for s in story: s.delete() elif len(story) == 0: story_revision = StoryRevision( changeset=changeset, type=StoryType.objects.get(name='cover'), pencils='?', inks='?', colors='?', sequence_number=0, page_count=2 if cover.is_wraparound else 1, ) story_revision.save() else: # this should never happen raise ValueError("More than one story sequence in a cover revision.") return HttpResponseRedirect(urlresolvers.reverse('compare', kwargs={'id': cover.changeset.id}))
def flip_artwork_flag(request, revision_id=None): """ flips the status in regard to variants with different cover artwork """ cover = get_object_or_404(CoverRevision, id=revision_id) changeset = cover.changeset if request.user != changeset.approver: return render_error( request, 'The variant artwork status may only be changed by the approver.') story = list(changeset.storyrevisions.all()) if len(story) == 1: for s in story: s.delete() elif len(story) == 0: story_revision = StoryRevision( changeset=changeset, type=StoryType.objects.get(name='cover'), pencils='?', inks='?', colors='?', sequence_number=0, page_count=2 if cover.is_wraparound else 1, ) story_revision.save() else: # this should never happen raise ValueError("More than one story sequence in a cover revision.") return HttpResponseRedirect( urlresolvers.reverse('compare', kwargs={'id': cover.changeset.id}))
def test_save_target_rev_issue_mismatch(patched_for_save): save_mock, origin, target = patched_for_save r = ReprintRevision(origin=origin, origin_issue=origin.issue, origin_revision=StoryRevision(story=origin, issue=origin.issue), target=None, target_issue=origin.issue, target_revision=StoryRevision(story=target)) with pytest.raises(ValueError) as exc_info: r.save() assert not save_mock.called v = str(exc_info.value) assert "target story revision issue and target issue do not agree" in v assert ("'%s'; Issue: '%s'" % (r.target_revision.issue, r.target_issue)) in v
def test_save_origin_rev_story_mismatch(patched_for_save): save_mock, origin, target = patched_for_save r = ReprintRevision(origin=origin, origin_issue=origin.issue, origin_revision=StoryRevision(story=None, issue=origin.issue), target=target, target_issue=target.issue, target_revision=StoryRevision(story=target, issue=target.issue)) with pytest.raises(ValueError) as exc_info: r.save() assert not save_mock.called v = str(exc_info.value) assert "origin story revision and origin story do not agree" in v assert ("'%s'; Story: '%s'" % (r.origin_revision.story, r.origin)) in v
def convert(self, changeset): from apps.gcd.migration.history.migrate_status import convert_story_type # Fix types story_type = convert_story_type(self) if Story.objects.filter(id=self.id).exists(): story_id = self.id else: story_id = None try: page_count = float(self.page_count) except: page_count = None revision = StoryRevision(changeset=changeset, story_id=story_id, issue_id=self.issue_id, sequence_number=self.sequence_number, title=self.title, feature=self.feature, type=story_type, page_count=page_count, script=self.script, pencils=self.pencils, inks=self.inks, colors=self.colors, letters=self.letters, editing=self.editing, genre=self.genre, characters=self.characters, synopsis=self.synopsis, reprint_notes=self.reprint_notes, job_number=self.job_number, notes=self.notes) revision.save() return revision
def patched_for_commit(patched_for_save): # We don't actually need save patched, but it's harmless and easy. save_mock, origin, target = patched_for_save with mock.patch('apps.oi.models.StoryRevision.commit_to_display'), \ mock.patch('apps.oi.models.StoryRevision.refresh_from_db'), \ mock.patch('apps.oi.models.Revision.open', new_callable=mock.PropertyMock) as open_mock: # By default, assume not open, and committed=True c = Changeset() open_mock.return_value = False origin_rev = StoryRevision(changeset=c, story=origin, committed=True) target_rev = StoryRevision(changeset=c, story=target, committed=True) # Need to track instance calls separately. origin_rev.commit_to_display = mock.MagicMock() target_rev.commit_to_display = mock.MagicMock() yield origin_rev, target_rev, open_mock
def _import_sequences(request, issue_id, changeset, lines, running_number): """ Processing of story lines happens here. lines is a list of lists. This routine is independent of a particular format of the file, as long as the order of the fields in lines matches. """ for fields in lines: story_type, failure = _find_story_type(request, changeset, fields) if failure: return story_type title = fields[TITLE].strip() first_line = fields[FIRST_LINE].strip() if title.startswith('[') and title.endswith(']'): title = title[1:-1] title_inferred = True else: title_inferred = False feature = fields[FEATURE].strip() page_count, page_count_uncertain = \ _check_page_count(fields[STORY_PAGE_COUNT]) script, no_script = _check_for_none(fields[SCRIPT]) if story_type == StoryType.objects.get(name='cover'): if not script: no_script = True pencils, no_pencils = _check_for_none(fields[PENCILS]) inks, no_inks = _check_for_none(fields[INKS]) colors, no_colors = _check_for_none(fields[COLORS]) letters, no_letters = _check_for_none(fields[LETTERS]) editing, no_editing = _check_for_none(fields[STORY_EDITING]) genres = fields[GENRE].strip() if genres: filtered_genres = '' for genre in genres.split(';'): if genre.strip() in GENRES['en']: filtered_genres += ';' + genre genre = filtered_genres[1:] else: genre = genres characters = fields[CHARACTERS].strip() job_number = fields[JOB_NUMBER].strip() reprint_notes = fields[REPRINT_NOTES].strip() synopsis = fields[SYNOPSIS].strip() notes = fields[STORY_NOTES].strip() keywords = fields[STORY_KEYWORDS].strip() story_revision = StoryRevision( changeset=changeset, title=title, title_inferred=title_inferred, first_line=first_line, feature=feature, type=story_type, sequence_number=running_number, page_count=page_count, page_count_uncertain=page_count_uncertain, script=script, pencils=pencils, inks=inks, colors=colors, letters=letters, editing=editing, no_script=no_script, no_pencils=no_pencils, no_inks=no_inks, no_colors=no_colors, no_letters=no_letters, no_editing=no_editing, job_number=job_number, genre=genre, characters=characters, synopsis=synopsis, reprint_notes=reprint_notes, notes=notes, keywords=keywords, issue=Issue.objects.get(id=issue_id) ) story_revision.save() running_number += 1 return HttpResponseRedirect(urlresolvers.reverse('edit', kwargs={'id': changeset.id}))
def handle_uploaded_cover(request, cover, issue, variant=False, revision_lock=None): ''' process the uploaded file and generate CoverRevision ''' try: if variant: form = UploadVariantScanForm(request.POST, request.FILES) else: form = UploadScanForm(request.POST, request.FILES) except IOError: # sometimes uploads misbehave. connection dropped ? error_text = 'Something went wrong with the upload. ' + \ 'Please <a href="' + request.path + '">try again</a>.' return render_error(request, error_text, redirect=False, is_safe=True) if not form.is_valid(): return _display_cover_upload_form(request, form, cover, issue, variant=variant) # process form if form.cleaned_data['is_gatefold']: return handle_gatefold_cover(request, cover, issue, form) scan = form.cleaned_data['scan'] file_source = form.cleaned_data['source'] marked = form.cleaned_data['marked'] # create OI records changeset = Changeset(indexer=request.user, state=states.OPEN, change_type=CTYPES['cover']) changeset.save() if cover: # upload_type is 'replacement': revision = CoverRevision(changeset=changeset, issue=issue, cover=cover, file_source=file_source, marked=marked, is_replacement=True) revision_lock.changeset = changeset revision_lock.save() revision.previous_revision = cover.revisions.get( next_revision=None, changeset__state=states.APPROVED, committed=True) else: revision = CoverRevision(changeset=changeset, issue=issue, file_source=file_source, marked=marked) revision.save() # if uploading a variant, generate an issue_revision for # the variant issue and copy the values which would not change # TODO are these reasonable assumptions below ? if variant: current_variants = issue.variant_set.all().order_by('-sort_code') if current_variants: add_after = current_variants[0] else: add_after = issue issue_revision = IssueRevision( changeset=changeset, after=add_after, number=issue.number, title=issue.title, no_title=issue.no_title, volume=issue.volume, no_volume=issue.no_volume, display_volume_with_number=issue.display_volume_with_number, variant_of=issue, variant_name=form.cleaned_data['variant_name'], page_count=issue.page_count, page_count_uncertain=issue.page_count_uncertain, series=issue.series, editing=issue.editing, no_editing=issue.no_editing, reservation_requested=form.cleaned_data['reservation_requested']) issue_revision.save() if form.cleaned_data['variant_artwork']: story_revision = StoryRevision( changeset=changeset, type=StoryType.objects.get(name='cover'), no_script=True, pencils='?', inks='?', colors='?', no_letters=True, no_editing=True, sequence_number=0, page_count=2 if form.cleaned_data['is_wraparound'] else 1, ) story_revision.save() # put new uploaded covers into # media/<LOCAL_NEW_SCANS>/<monthname>_<year>/ # with name # <revision_id>_<date>_<time>.<ext> scan_name = str(revision.id) + os.path.splitext(scan.name)[1] upload_dir = settings.MEDIA_ROOT + LOCAL_NEW_SCANS + \ changeset.created.strftime('%B_%Y').lower() destination_name = os.path.join(upload_dir, scan_name) try: # essentially only needed at beginning of the month check_cover_dir(upload_dir) except IOError: changeset.delete() error_text = "Problem with file storage for uploaded " + \ "cover, please report an error." return render_error(request, error_text, redirect=False) # write uploaded file destination = open(destination_name, 'wb') for chunk in scan.chunks(): destination.write(chunk) destination.close() try: # generate different sizes we are using im = pyImage.open(destination.name) large_enough = False if form.cleaned_data['is_wraparound']: # wraparounds need to have twice the width if im.size[0] >= 800 and im.size[1] >= 400: large_enough = True elif min(im.size) >= 400: large_enough = True if large_enough: if form.cleaned_data['is_wraparound']: revision.is_wraparound = True revision.front_left = im.size[0] / 2 revision.front_right = im.size[0] revision.front_bottom = im.size[1] revision.front_top = 0 revision.save() generate_sizes(revision, im) else: changeset.delete() os.remove(destination.name) info_text = "Image is too small, only " + str(im.size) + \ " in size." return _display_cover_upload_form(request, form, cover, issue, info_text=info_text, variant=variant) except IOError as e: # just in case, django *should* have taken care of file type changeset.delete() os.remove(destination.name) info_text = 'Error: File \"' + scan.name + \ '" is not a valid picture.' return _display_cover_upload_form(request, form, cover, issue, info_text=info_text, variant=variant) # all done, we can save the state return finish_cover_revision(request, revision, form.cleaned_data)
def handle_uploaded_cover(request, cover, issue, variant=False, revision_lock=None): ''' process the uploaded file and generate CoverRevision ''' try: if variant: form = UploadVariantScanForm(request.POST, request.FILES) else: form = UploadScanForm(request.POST, request.FILES) except IOError: # sometimes uploads misbehave. connection dropped ? error_text = 'Something went wrong with the upload. ' + \ 'Please <a href="' + request.path + '">try again</a>.' return render_error(request, error_text, redirect=False, is_safe=True) if not form.is_valid(): return _display_cover_upload_form(request, form, cover, issue, variant=variant) # process form if form.cleaned_data['is_gatefold']: return handle_gatefold_cover(request, cover, issue, form) scan = form.cleaned_data['scan'] file_source = form.cleaned_data['source'] marked = form.cleaned_data['marked'] # create OI records changeset = Changeset(indexer=request.user, state=states.OPEN, change_type=CTYPES['cover']) changeset.save() if cover: # upload_type is 'replacement': revision = CoverRevision(changeset=changeset, issue=issue, cover=cover, file_source=file_source, marked=marked, is_replacement = True) revision_lock.changeset = changeset revision_lock.save() revision.previous_revision = cover.revisions.get( next_revision=None, changeset__state=states.APPROVED, committed=True) else: revision = CoverRevision(changeset=changeset, issue=issue, file_source=file_source, marked=marked) revision.save() # if uploading a variant, generate an issue_revision for # the variant issue and copy the values which would not change # TODO are these reasonable assumptions below ? if variant: current_variants = issue.variant_set.all().order_by('-sort_code') if current_variants: add_after = current_variants[0] else: add_after = issue issue_revision = IssueRevision(changeset=changeset, after=add_after, number=issue.number, title=issue.title, no_title=issue.no_title, volume=issue.volume, no_volume=issue.no_volume, display_volume_with_number=issue.display_volume_with_number, variant_of=issue, variant_name=form.cleaned_data['variant_name'], page_count=issue.page_count, page_count_uncertain=issue.page_count_uncertain, series=issue.series, editing=issue.editing, no_editing=issue.no_editing, reservation_requested=form.cleaned_data['reservation_requested'] ) issue_revision.save() if form.cleaned_data['variant_artwork']: story_revision = StoryRevision(changeset=changeset, type=StoryType.objects.get(name='cover'), no_script=True, pencils='?', inks='?', colors='?', no_letters=True, no_editing=True, sequence_number=0, page_count=2 if form.cleaned_data['is_wraparound'] else 1, ) story_revision.save() # put new uploaded covers into # media/<LOCAL_NEW_SCANS>/<monthname>_<year>/ # with name # <revision_id>_<date>_<time>.<ext> scan_name = str(revision.id) + os.path.splitext(scan.name)[1] upload_dir = settings.MEDIA_ROOT + LOCAL_NEW_SCANS + \ changeset.created.strftime('%B_%Y').lower() destination_name = os.path.join(upload_dir, scan_name) try: # essentially only needed at beginning of the month check_cover_dir(upload_dir) except IOError: changeset.delete() error_text = "Problem with file storage for uploaded " + \ "cover, please report an error." return render_error(request, error_text, redirect=False) # write uploaded file destination = open(destination_name, 'wb') for chunk in scan.chunks(): destination.write(chunk) destination.close() try: # generate different sizes we are using im = pyImage.open(destination.name) large_enough = False if form.cleaned_data['is_wraparound']: # wraparounds need to have twice the width if im.size[0] >= 800 and im.size[1] >= 400: large_enough = True elif min(im.size) >= 400: large_enough = True if large_enough: if form.cleaned_data['is_wraparound']: revision.is_wraparound = True revision.front_left = im.size[0]/2 revision.front_right = im.size[0] revision.front_bottom = im.size[1] revision.front_top = 0 revision.save() generate_sizes(revision, im) else: changeset.delete() os.remove(destination.name) info_text = "Image is too small, only " + str(im.size) + \ " in size." return _display_cover_upload_form(request, form, cover, issue, info_text=info_text, variant=variant) except IOError as e: # just in case, django *should* have taken care of file type changeset.delete() os.remove(destination.name) info_text = 'Error: File \"' + scan.name + \ '" is not a valid picture.' return _display_cover_upload_form(request, form, cover, issue, info_text=info_text, variant=variant) # all done, we can save the state return finish_cover_revision(request, revision, form.cleaned_data)
def test_stats_category_field_tuples(): assert StoryRevision._get_stats_category_field_tuples() == { ('issue', 'series', 'country'), ('issue', 'series', 'language'), }
def any_edit_story_rev(any_added_story, any_editing_changeset): rev = StoryRevision.clone(data_object=any_added_story, changeset=any_editing_changeset) return rev
def any_added_story_rev(any_adding_changeset, story_add_values): rev = StoryRevision(changeset=any_adding_changeset, **story_add_values) rev.save() return rev
def _import_sequences(request, issue_id, changeset, lines, running_number): """ Processing of story lines happens here. lines is a list of lists. This routine is independent of a particular format of the file, as long as the order of the fields in lines matches. """ for fields in lines: story_type, failure = _find_story_type(request, changeset, fields) if failure: return story_type title = fields[TITLE].strip() if title.startswith('[') and title.endswith(']'): title = title[1:-1] title_inferred = True else: title_inferred = False feature = fields[FEATURE].strip() page_count, page_count_uncertain = \ _check_page_count(fields[STORY_PAGE_COUNT]) script, no_script = _check_for_none(fields[SCRIPT]) if story_type == StoryType.objects.get(name='cover'): if not script: no_script = True pencils, no_pencils = _check_for_none(fields[PENCILS]) inks, no_inks = _check_for_none(fields[INKS]) colors, no_colors = _check_for_none(fields[COLORS]) letters, no_letters = _check_for_none(fields[LETTERS]) editing, no_editing = _check_for_none(fields[STORY_EDITING]) genre = fields[GENRE].strip() characters = fields[CHARACTERS].strip() job_number = fields[JOB_NUMBER].strip() reprint_notes = fields[REPRINT_NOTES].strip() synopsis = fields[SYNOPSIS].strip() notes = fields[STORY_NOTES].strip() keywords = fields[STORY_KEYWORDS].strip() story_revision = StoryRevision(changeset=changeset, title=title, title_inferred=title_inferred, feature=feature, type=story_type, sequence_number=running_number, page_count=page_count, page_count_uncertain = page_count_uncertain, script = script, pencils = pencils, inks = inks, colors = colors, letters = letters, editing = editing, no_script = no_script, no_pencils = no_pencils, no_inks = no_inks, no_colors = no_colors, no_letters = no_letters, no_editing = no_editing, job_number = job_number, genre = genre, characters = characters, synopsis = synopsis, reprint_notes = reprint_notes, notes = notes, keywords = keywords, issue = Issue.objects.get(id=issue_id) ) story_revision.save() running_number += 1 return HttpResponseRedirect(urlresolvers.reverse('edit', kwargs={ 'id': changeset.id }))