Пример #1
0
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}))
Пример #2
0
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}))
Пример #3
0
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
Пример #4
0
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
Пример #5
0
    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
Пример #6
0
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
Пример #7
0
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}))
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
def test_stats_category_field_tuples():
    assert StoryRevision._get_stats_category_field_tuples() == {
        ('issue', 'series', 'country'),
        ('issue', 'series', 'language'),
    }
Пример #11
0
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
Пример #12
0
def any_added_story_rev(any_adding_changeset, story_add_values):
    rev = StoryRevision(changeset=any_adding_changeset, **story_add_values)
    rev.save()
    return rev
Пример #13
0
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
Пример #14
0
def any_added_story_rev(any_adding_changeset, story_add_values):
    rev = StoryRevision(changeset=any_adding_changeset, **story_add_values)
    rev.save()
    return rev
Пример #15
0
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 }))