Skip to content

Commit

Permalink
Merge pull request #1410 from scieloorg/beta
Browse files Browse the repository at this point in the history
Incorporação de códigos estáveis
  • Loading branch information
gustavofonseca authored Mar 21, 2017
2 parents 7168780 + 6cd9cb0 commit 088b712
Show file tree
Hide file tree
Showing 13 changed files with 1,144 additions and 411 deletions.
10 changes: 5 additions & 5 deletions docs/dev/exporttoisis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ Para a nova versão da ferramenta de gestão de periódicos, considerando as car
Introdução
----------

As bases de dados ISIS geradas pelo Title Manager são utilizadas em dois prontos do processo de publicação da SciELO, são eles: processo de marcação e processamento para inclusão de conteúdo.
As bases de dados ISIS geradas pelo Title Manager são utilizadas em dois pontos do processo de publicação da SciELO, são eles: processo de marcação e processamento para inclusão de conteúdo.

Processamento para inclusão de conteúdo
=======================================

Atualmente o SciELO possui um processamento (geraPadrao.bat) para inclusão de novas revistas, fascículos e artigos na coleção. Esse processamento recebe como entrada um conjunto de bases de dados, são elas: artigo, issue, code, title.

As bases code, title e issue são únicadas para todo o processamento, significa que uma base de dados com todo o conteúdo de título, outra com todo conteúdo de code e outra com todo conteúdo de issues são geradas e gravadas em um diretório chamado serial gerando a seguinte estrutura de dados de entrada para o processamento.
As bases code, title e issue são únicas para todo o processamento, significa que uma base de dados com todo o conteúdo de título, outra com todo conteúdo de code e outra com todo conteúdo de issues são geradas e gravadas em um diretório chamado serial gerando a seguinte estrutura de dados de entrada para o processamento.

.. code-block:: text
Expand Down Expand Up @@ -74,7 +74,7 @@ Em resumo, significa que o processo de exportação de bases do SciELO Manager p
Processo de Marcação
====================

O processo de marcação de metadados de artigos nas SciELO é feito através da ferramenta Markup, que corresponde a um aplicativo VBSript embutido no Word para identificar os elementos dos artigos. Esse plugin do Word consulta algumas bases de dados ISIS geradas pela Title Manager para complementar a identificação de elementos no texto do artigo, como por exemplo:
O processo de marcação de metadados de artigos nas SciELO é feito através da ferramenta Markup, que corresponde a um aplicativo VBScript embutido no Word para identificar os elementos dos artigos. Esse plugin do Word consulta algumas bases de dados ISIS geradas pela Title Manager para complementar a identificação de elementos no texto do artigo, como por exemplo:

* Identificação de seções dos fascículos (base code)

Expand Down Expand Up @@ -334,7 +334,7 @@ Title
quando mais de uma coleção compartilha mesma base title no site local. Resolver este problema
criando instalações independentes para cada coleção SciELO, ex: Brasil e Saúde Pública.

Foram encontradas ocorrencias do campo v691 no arquivo sci_serial.xis entretanto parece não estar
Foram encontradas ocorrências do campo v691 no arquivo sci_serial.xis entretanto parece não estar
em uso uma vez que faz referência a arquivos template (ScieloXML/collections.xis) que não estão
atualizados.

Expand Down Expand Up @@ -418,4 +418,4 @@ Title

20. Seção (130)

Excluído da aplicação. Não precisa ser mantido para compatibilidade. Nunca foi usado
Excluído da aplicação. Não precisa ser mantido para compatibilidade. Nunca foi usado
7 changes: 3 additions & 4 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@ yuicompressor
jsonfield
django-tastypie==0.9.16
django-htmlmin==0.7.0
packtools==1.3.1
Celery
django-celery
django-kombu
packtools==1.3.3
celery==3.1.25
django-celery==3.1.16
defusedxml==0.4.1
cython
thriftpy
Expand Down

Large diffs are not rendered by default.

401 changes: 401 additions & 0 deletions scielomanager/journalmanager/migrations/0033_update_issue_label.py

Large diffs are not rendered by default.

32 changes: 29 additions & 3 deletions scielomanager/journalmanager/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@
from scielo_extensions import modelfields
from tastypie.models import create_api_key
import celery
from PIL import Image

from scielomanager.utils import base28
from scielomanager.custom_fields import ContentTypeRestrictedFileField, XMLSPSField
from scielomanager.custom_fields import (
ContentTypeRestrictedFileField,
XMLSPSField,
)
from . import modelmanagers


Expand Down Expand Up @@ -993,7 +997,8 @@ def identification(self):
values.append('suppl.%s' % self.suppl_text)

if self.type == 'special':
values.append('spe.%s' % self.spe_text)
_spe_text = 'spe' + self.spe_text if self.spe_text else 'spe'
values.append(_spe_text)

return ' '.join([val for val in values if val]).strip().replace('ahead', 'ahead of print')

Expand Down Expand Up @@ -1497,8 +1502,12 @@ class ArticleAsset(models.Model):
"""
article = models.ForeignKey('Article', on_delete=models.CASCADE,
related_name='assets')
file = models.FileField(upload_to=make_article_directory_path('assets'),
file = models.FileField(
upload_to=make_article_directory_path('assets'),
max_length=1024)
preferred_alt_file = models.FileField(
upload_to=make_article_directory_path('alt_assets'),
max_length=1024, default=u'')
owner = models.CharField(max_length=1024, default=u'')
use_license = models.TextField(default=u'')
updated_at = models.DateTimeField(auto_now=True)
Expand All @@ -1507,6 +1516,23 @@ def __repr__(self):
return u'<%s id="%s" url="%s">' % (self.__class__.__name__,
self.pk, self.file.url)

def is_image(self):
"""Verifica se o ativo digital é uma imagem.
"""
try:
img = Image.open(self.file)
except IOError:
return False
else:
return True

@property
def best_file(self):
if self.preferred_alt_file:
return self.preferred_alt_file
else:
return self.file


class ArticleHTMLRendition(models.Model):
"""Documento HTML de uma tradução de uma instância de Article.
Expand Down
85 changes: 85 additions & 0 deletions scielomanager/journalmanager/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from celery.utils.log import get_task_logger
from django.templatetags.static import static
import packtools
from PIL import Image

from scielomanager.celery import app
from scielomanager import connectors
Expand Down Expand Up @@ -389,10 +390,14 @@ def create_articleasset_from_bytes(aid, filename, content, owner=None,
_owner = owner or u''
_use_license = use_license or u''

# create and save the asset
asset = models.ArticleAsset(article=article, owner=_owner,
use_license=_use_license)
asset.file.save(filename, ContentFile(content))

# create a preferred alternative for the asset
create_preferred_image_file.delay(asset.pk)

logger.info('New ArticleAsset %s added to Article with aid: %s.',
repr(asset), aid)

Expand Down Expand Up @@ -434,3 +439,83 @@ def create_article_html_renditions(article_pk, css_url=None, valid_only=False):

return files_urls


def convert_image_to_jpeg(filepath, mode=None, **kwargs):
"""Converte a imagem no caminho `filepath` para o formato JPEG.
Retorna um buffer com o conteúdo convertido da imagem. Pode levantar
`ValueError` caso `filepath` não seja reconhecido como uma imagem.
:param **kwargs: (opcional) argumentos nomeados serão repassados para a
função `Image.save`, com exceção de `format` que foi pré-definido.
"""
output_buffer = io.BytesIO()
_ = kwargs.pop('format', None)

original = Image.open(filepath)
if mode:
_image = original.convert(mode=mode)
else:
_image = original

_image.save(output_buffer, format='jpeg', **kwargs)

return output_buffer


@app.task(throws=(ValueError, TypeError,))
def create_preferred_image_file(asset_pk):
"""Cria uma versão alternativa de `ArticleAsset.file`, preferida para o
manuseio.
Por hora a versão preferida é o JPEG ao invés de TIFF. Para os demais
formatos não serão geradas outras versões.
:param asset_pk: chave primária da instância de `ArticleAsset`.
"""
try:
asset = models.ArticleAsset.objects.get(pk=asset_pk)

except models.ArticleAsset.DoesNotExist:
raise ValueError('Cannot find ArticleAsset with pk: %s' % asset_pk)

try:
filepath = asset.file.path
except ValueError as exc:
logger.exception(exc)
logger.error('Cannot create a preferred alt file for %s. Skipping.',
filepath)
raise

if not asset.is_image():
logger.error('Cannot create a preferred alt file for %s. Skipping.',
filepath)
raise ValueError('Cannot create preferred alternatives for files '
'other than images.')

_file = Image.open(asset.file.path)
if _file.format.lower() != 'tiff':
raise ValueError('Image is already in a preferred format.')

try:
# Levanta IOError caso `filepath` não seja um arquivo de imagem.
jpeg_buffer = convert_image_to_jpeg(filepath)
except IOError as exc:
logger.exception(exc)
logger.error('Cannot create a preferred alt file for %s. Skipping.',
filepath)
raise

_, filename = os.path.split(filepath)
filename_head, _ = os.path.splitext(filename)

jpeg_filename = filename_head + '.jpeg'

asset.preferred_alt_file.save(jpeg_filename,
ContentFile(jpeg_buffer.getvalue()))

logger.info('Finished creating an alternative file for %s.',
repr(asset))

return asset.preferred_alt_file.url

Binary file not shown.
15 changes: 15 additions & 0 deletions scielomanager/journalmanager/tests/modelfactories.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from journalmanager import models
from django.contrib.auth.models import Group
from django.core.files.base import File


_HERE = os.path.dirname(os.path.abspath(__file__))
Expand All @@ -15,6 +16,10 @@
SAMPLE_XML = xml_file.read()


SAMPLE_TIFF_IMAGE = open(
os.path.join(_HERE, 'image_test', 'sample_tif_image.tif'))


with open(os.path.join(_HERE, 'xml_samples', '0034-8910-rsp-48-2-0216_related.xml')) as xml_file:
SAMPLE_XML_RELATED = xml_file.read()

Expand Down Expand Up @@ -232,3 +237,13 @@ class ArticleFactory(factory.Factory):
article_type = u'research-article'
doi = u'10.1590/S0034-8910.2014048004965'


class ArticleAssetFactory(factory.Factory):
FACTORY_FOR = models.ArticleAsset

article = factory.SubFactory(ArticleFactory)
file = File(SAMPLE_TIFF_IMAGE)
owner = u'SciELO'
use_license = u'Creative Commons - BY'


2 changes: 1 addition & 1 deletion scielomanager/journalmanager/tests/tests_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def test_identification_for_ahead(self):

def test_identification_for_special(self):
issue = IssueFactory.create(number='1', spe_text='2', type='special')
expected = u'1 spe.2'
expected = u'1 spe2'

self.assertEqual(issue.identification, expected)

Expand Down
101 changes: 101 additions & 0 deletions scielomanager/journalmanager/tests/tests_tasks.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#coding: utf-8
import os
import io
import copy
import unittest
Expand Down Expand Up @@ -898,3 +899,103 @@ def test_htmls_filenames_are_suffixed_with_lang(self):
for url, lang in urls:
self.assertTrue(url.endswith(u'-' + lang + u'.html'))


class ConvertImageToJpegTests(TestCase):
def test_convert_gif_image_to_jpeg(self):
from PIL import Image
image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
u'image_test', u'cover_too_heavy.gif')

# A conversão de GIF para JPEG depende da conversão do modo para a
# profundidade de cor por pixel. Por isso do argumento `mode`.
jpeg_buff = tasks.convert_image_to_jpeg(image_path, mode='RGB')
jpeg_buff.seek(0)

img = Image.open(jpeg_buff)
self.assertEquals(img.format.lower(), 'jpeg')

def test_convert_tif_image_to_jpeg(self):
from PIL import Image
image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
u'image_test', u'sample_tif_image.tif')

jpeg_buff = tasks.convert_image_to_jpeg(image_path)
jpeg_buff.seek(0)

img = Image.open(jpeg_buff)
self.assertEquals(img.format.lower(), 'jpeg')

def test_convert_pdf_to_jpeg(self):
"""That should raise a IOError.
"""
from PIL import Image
image_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
u'image_test', u'logo.pdf')

self.assertRaises(IOError,
lambda: tasks.convert_image_to_jpeg(image_path))


class CreatePreferredImageFileTests(TestCase):
def setUp(self):
self.unlink_registry = []

def tearDown(self):
for path in self.unlink_registry:
os.unlink(path)

def test_create_alt_image_from_tiff(self):
asset = modelfactories.ArticleAssetFactory.create()
self.assertEquals(False, bool(asset.preferred_alt_file))

tasks.create_preferred_image_file(asset.pk)

modified_asset = models.ArticleAsset.objects.get(pk=asset.pk)
self.assertEquals(True, bool(modified_asset.preferred_alt_file))

# evitar que arquivos temporários sobrem no disco.
self.unlink_registry.append(asset.file.path)
self.unlink_registry.append(modified_asset.preferred_alt_file.path)

def test_alt_to_tiff_is_jpeg(self):
from PIL import Image
asset = modelfactories.ArticleAssetFactory.create()
tasks.create_preferred_image_file(asset.pk)
modified_asset = models.ArticleAsset.objects.get(pk=asset.pk)
self.assertEquals('jpeg',
Image.open(modified_asset.preferred_alt_file.path).format.lower())

# evitar que arquivos temporários sobrem no disco.
self.unlink_registry.append(asset.file.path)
self.unlink_registry.append(modified_asset.preferred_alt_file.path)

def test_non_images_raise_ValueError(self):
from django.core.files.base import File
SAMPLE_PDF = open(os.path.join(
os.path.dirname(os.path.abspath(__file__)),
u'image_test',
u'logo.pdf'))

asset = modelfactories.ArticleAssetFactory.build()
asset.file = File(SAMPLE_PDF)

self.assertRaises(ValueError,
lambda: tasks.create_preferred_image_file(asset.pk))

def test_images_other_than_tiff_raise_ValueError(self):
from django.core.files.base import File
SAMPLE_PDF = open(os.path.join(
os.path.dirname(os.path.abspath(__file__)),
u'image_test',
u'cover.gif'))

asset = modelfactories.ArticleAssetFactory.build()
asset.file = File(SAMPLE_PDF)

self.assertRaises(ValueError,
lambda: tasks.create_preferred_image_file(asset.pk))

def test_missing_asset_raise_ValueError(self):
self.assertRaises(ValueError,
lambda: tasks.create_preferred_image_file(999999))

Loading

0 comments on commit 088b712

Please sign in to comment.