diff --git a/tests/test_document.py b/tests/test_document.py index 5c92bfe..da9f9a0 100644 --- a/tests/test_document.py +++ b/tests/test_document.py @@ -2743,6 +2743,88 @@ def test_invalid_document_type(self): article.data['article']['v71'] = [{u'_': u'invalid'}] self.assertEqual(article.document_type, u'undefined') + def test_document_type_from_article_type_attribute(self): + article = self.article + + for article_type in [ + 'abstract', 'addendum', 'announcement', 'article-commentary', + 'book-review', 'books-received', 'brief-report', 'calendar', + 'case-report', 'clinical-instruction', 'clinical-trial', + 'collection', 'correction', 'data-article', 'discussion', + 'dissertation', 'editorial', 'editorial-material', + 'expression-of-concern', 'guideline', 'in-brief', 'interview', + 'introduction', 'letter', 'meeting-report', 'news', 'obituary', + 'oration', 'other', 'partial-retraction', 'product-review', + 'rapid-communication', 'referee-report', 'reply', 'reprint', + 'research-article', 'retraction', 'review-article', + 'reviewer-report', 'technical-report', 'translation', + ]: + article.data['article']['v71'] = [{u'_': article_type}] + self.assertEqual(article.document_type, article_type) + + def test_document_type_from_legacy_v71_values(self): + article = self.article + + legacy_mappings = { + u'an': u'announcement', + u'in': u'interview', + u'pr': u'in-brief', + u'sc': u'rapid-communication', + u're': u'retraction', + } + + for legacy_value, expected_type in legacy_mappings.items(): + article.data['article']['v71'] = [{u'_': legacy_value}] + self.assertEqual(article.document_type, expected_type) + + def test_sps_doctype(self): + article = self.article + self.assertEqual(article.sps_doctype, u'research-article') + + def test_sps_doctype_from_legacy_code(self): + article = self.article + article.data['article']['v71'] = [{u'_': u'er'}] + self.assertEqual(article.sps_doctype, u'correction') + + def test_sps_doctype_from_article_type(self): + article = self.article + article.data['article']['v71'] = [{u'_': u'retraction'}] + self.assertEqual(article.sps_doctype, u'retraction') + + def test_sps_doctype_without_v71(self): + article = self.article + del(article.data['article']['v71']) + self.assertIsNone(article.sps_doctype) + + def test_sps_doctype_invalid(self): + article = self.article + article.data['article']['v71'] = [{u'_': u'invalid'}] + self.assertIsNone(article.sps_doctype) + + def test_legacy_doctype(self): + article = self.article + self.assertEqual(article.legacy_doctype, u'oa') + + def test_legacy_doctype_from_article_type(self): + article = self.article + article.data['article']['v71'] = [{u'_': u'retraction'}] + self.assertEqual(article.legacy_doctype, u're') + + def test_legacy_doctype_from_legacy_code(self): + article = self.article + article.data['article']['v71'] = [{u'_': u'er'}] + self.assertEqual(article.legacy_doctype, u'er') + + def test_legacy_doctype_without_v71(self): + article = self.article + del(article.data['article']['v71']) + self.assertIsNone(article.legacy_doctype) + + def test_legacy_doctype_article_type_self_mapped(self): + article = self.article + article.data['article']['v71'] = [{u'_': u'data-article'}] + self.assertEqual(article.legacy_doctype, u'data-article') + def test_without_original_title(self): article = self.article diff --git a/xylose/choices.py b/xylose/choices.py index a78215b..ad25e2c 100644 --- a/xylose/choices.py +++ b/xylose/choices.py @@ -53,26 +53,109 @@ article_types = { 'ab': 'abstract', - 'an': 'news', + 'an': 'announcement', 'ax': 'addendum', 'co': 'article-commentary', 'cr': 'case-report', 'ct': 'research-article', 'ed': 'editorial', 'er': 'correction', - 'in': 'editorial', + 'in': 'interview', 'le': 'letter', - 'mt': 'research-article', + 'mt': 'review-article', 'nd': 'undefined', 'oa': 'research-article', - 'pr': 'press-release', + 'pr': 'in-brief', 'pv': 'editorial', + 're': 'retraction', 'rc': 'book-review', 'rn': 'brief-report', 'ra': 'review-article', 'sc': 'rapid-communication', 'tr': 'research-article', - 'up': 'undefined' + 'up': 'rapid-communication', + 'zz': 'other', + 'abstract': 'abstract', + 'addendum': 'addendum', + 'announcement': 'announcement', + 'article-commentary': 'article-commentary', + 'book-review': 'book-review', + 'books-received': 'books-received', + 'brief-report': 'brief-report', + 'calendar': 'calendar', + 'case-report': 'case-report', + 'clinical-instruction': 'clinical-instruction', + 'clinical-trial': 'clinical-trial', + 'collection': 'collection', + 'correction': 'correction', + 'data-article': 'data-article', + 'discussion': 'discussion', + 'dissertation': 'dissertation', + 'editorial': 'editorial', + 'editorial-material': 'editorial-material', + 'expression-of-concern': 'expression-of-concern', + 'guideline': 'guideline', + 'in-brief': 'in-brief', + 'interview': 'interview', + 'introduction': 'introduction', + 'letter': 'letter', + 'meeting-report': 'meeting-report', + 'news': 'news', + 'obituary': 'obituary', + 'oration': 'oration', + 'other': 'other', + 'partial-retraction': 'partial-retraction', + 'product-review': 'product-review', + 'rapid-communication': 'rapid-communication', + 'referee-report': 'referee-report', + 'reply': 'reply', + 'reprint': 'reprint', + 'research-article': 'research-article', + 'retraction': 'retraction', + 'review-article': 'review-article', + 'reviewer-report': 'reviewer-report', + 'technical-report': 'technical-report', + 'translation': 'translation', +} + +DOCTOPIC = { + 'research-article': 'oa', + 'editorial': 'ed', + 'abstract': 'ab', + 'announcement': 'an', + 'article-commentary': 'co', + 'case-report': 'cr', + 'letter': 'le', + 'review-article': 'ra', + 'rapid-communication': 'sc', + 'addendum': 'addendum', + 'book-review': 'rc', + 'books-received': 'books-received', + 'brief-report': 'rn', + 'calendar': 'calendar', + 'clinical-trial': 'oa', + 'collection': 'zz', + 'correction': 'er', + 'discussion': 'discussion', + 'dissertation': 'dissertation', + 'editorial-material': 'ed', + 'in-brief': 'pr', + 'introduction': 'ed', + 'meeting-report': 'meeting-report', + 'news': 'news', + 'obituary': 'obituary', + 'oration': 'oration', + 'partial-retraction': 'partial-retraction', + 'product-review': 'product-review', + 'reply': 'reply', + 'reprint': 'reprint', + 'retraction': 're', + 'translation': 'translation', + 'technical-report': 'oa', + 'other': 'zz', + 'guideline': 'guideline', + 'interview': 'in', + 'data-article': 'data-article', } periodicity = { diff --git a/xylose/scielodocument.py b/xylose/scielodocument.py index be1fcd2..9a7fa22 100644 --- a/xylose/scielodocument.py +++ b/xylose/scielodocument.py @@ -2234,6 +2234,37 @@ def document_type(self): return choices.article_types['nd'] + @property + def sps_doctype(self): + """ + This method retrieves the SPS @article-type of the given article. + Maps the v71 field value (legacy code or @article-type) to the + corresponding SPS @article-type value. + """ + if 'v71' in self.data['article']: + article_type_code = self.data['article']['v71'][0]['_'] + if article_type_code in choices.article_types: + return choices.article_types[article_type_code] + + return None + + @property + def legacy_doctype(self): + """ + This method retrieves the legacy document type code of the given article. + Maps the v71 field value (legacy code or @article-type) to the + corresponding legacy code using the DOCTOPIC reverse mapping. + """ + if 'v71' in self.data['article']: + article_type_code = self.data['article']['v71'][0]['_'] + # If the v71 value is an @article-type, look up the legacy code + if article_type_code in choices.DOCTOPIC: + return choices.DOCTOPIC[article_type_code] + # Otherwise return the value as-is (it may be a legacy code) + return article_type_code + + return None + def original_title(self, iso_format=None): """ This method retrieves just the title related with the original language