Module manubot.cite.tests.test_csl_item
View Source
import copy
import datetime
import pytest
from ..csl_item import (
CSL_Item,
assert_csl_item_type,
date_parts_to_string,
date_to_date_parts,
)
class Test_CSL_Item:
def test_constuctor_empty(self):
assert CSL_Item() == {}
def test_constuctor_by_dict(self):
d = {"title": "My book"}
assert CSL_Item(d) == d
def test_constuctor_by_keyword(self):
assert CSL_Item(type="journal-article") == {"type": "journal-article"}
def test_constuctor_by_dict_keyword_combination(self):
assert CSL_Item({"title": "My journal article"}, type="journal-article") == {
"title": "My journal article",
"type": "journal-article",
}
def test_recursive_constructor(self):
assert CSL_Item(CSL_Item()) == {}
assert CSL_Item(CSL_Item(abc=1)) == {"abc": 1}
def test_constructor_leaves_no_inplace_effects(self):
dict1 = {"a": 1}
ci = CSL_Item(dict1, b=2)
assert ci == {"a": 1, "b": 2}
assert dict1 == {"a": 1}
def test_correct_invalid_type(self):
assert CSL_Item(type="journal-article").correct_invalid_type() == {
"type": "article-journal"
}
def test_set_default_type(self):
assert CSL_Item().set_default_type() == {"type": "entry"}
def test_no_change_of_type(self):
assert CSL_Item(type="book").correct_invalid_type() == {"type": "book"}
assert CSL_Item(type="book").set_default_type() == {"type": "book"}
def test_clean(self):
csl_item = CSL_Item(type="chapter", id="abc")
csl_item.clean(prune=True)
assert csl_item == {"type": "chapter", "id": "abc"}
def test_clean_set_id(self):
csl_item = CSL_Item(type="chapter")
csl_item.set_id("abc")
csl_item.clean(prune=True)
assert csl_item == {"type": "chapter", "id": "abc"}
def test_assert_csl_item_type_passes():
assert_csl_item_type(CSL_Item())
def test_assert_csl_item_type_raises_error_on_dict():
with pytest.raises(TypeError):
assert_csl_item_type({})
@pytest.mark.parametrize(
["csl_item", "standard_citation"],
[
pytest.param(
{"id": "my-id", "standard_citation": "doi:10.7554/elife.32822"},
"doi:10.7554/elife.32822",
id="from_standard_citation",
),
pytest.param(
{"id": "doi:10.7554/elife.32822"},
"doi:10.7554/elife.32822",
id="from_doi_id",
),
pytest.param(
{"id": "DOI:10.7554/ELIFE.32822"},
"doi:10.7554/elife.32822",
id="from_doi_id_standardize",
),
pytest.param({"id": "my-id"}, "my-id", id="from_raw_id"),
],
)
def test_csl_item_standardize_id(csl_item, standard_citation):
csl_item = CSL_Item(csl_item)
output = csl_item.standardize_id()
assert output is csl_item
assert output["id"] == standard_citation
def test_csl_item_standardize_id_repeated():
csl_item = CSL_Item(id="pmid:1", type="article-journal")
csl_item_1 = copy.deepcopy(csl_item.standardize_id())
assert "standard_citation" not in "csl_item"
csl_item_2 = copy.deepcopy(csl_item.standardize_id())
assert csl_item_1 == csl_item_2
def test_csl_item_standardize_id_note():
"""
Test extracting standard_id from a note and setting additional
note fields.
"""
csl_item = CSL_Item(
{
"id": "original-id",
"type": "article-journal",
"note": "standard_id: doi:10.1371/journal.PPAT.1006256",
}
)
csl_item.standardize_id()
assert csl_item["id"] == "doi:10.1371/journal.ppat.1006256"
note_dict = csl_item.note_dict
assert note_dict["original_id"] == "original-id"
assert note_dict["original_standard_id"] == "doi:10.1371/journal.PPAT.1006256"
@pytest.mark.parametrize(
["input_note", "text", "dictionary", "expected_note"],
[
("", "", {}, ""),
(None, "", {}, ""),
("preexisting note", "", {}, "preexisting note"),
(
"preexisting note",
"",
{"key": "the value"},
"preexisting note\nkey: the value",
),
("", "", {"KEYOKAY": "the value"}, "KEYOKAY: the value"),
("preexisting note", "", {"KEY-NOT-OKAY": "the value"}, "preexisting note"),
(
"",
"",
{"standard_citation": "doi:10.7554/elife.32822"},
"standard_citation: doi:10.7554/elife.32822",
),
(
"This CSL Item was produced using Manubot.",
"",
{"standard_citation": "doi:10.7554/elife.32822"},
"This CSL Item was produced using Manubot.\nstandard_citation: doi:10.7554/elife.32822",
),
# do not append duplicate lines to a note
# https://github.com/manubot/manubot/issues/258
("Already exists.", "Already exists.", {}, "Already exists."),
("", "exists: yes", {"exists": "yes"}, "exists: yes"),
],
)
def test_csl_item_note_append(input_note, text, dictionary, expected_note):
csl_item = CSL_Item({"id": "test_csl_item", "type": "entry", "note": input_note})
csl_item.note_append_text(text)
csl_item.note_append_dict(dictionary)
assert csl_item.note == expected_note
@pytest.mark.parametrize(
["note", "dictionary"],
[
(
"This is a note\nkey_one: value\nKEYTWO: value 2 ",
{"key_one": "value", "KEYTWO": "value 2"},
),
("BAD_KEY: good value\ngood-key: good value", {"good-key": "good value"}),
(
"This is a note {:key_one: value} {:KEYTWO: value 2 } ",
{"key_one": "value", "KEYTWO": "value 2"},
),
("{:BAD_KEY: good value}\n{:good-key: good value}", {"good-key": "good value"}),
(
"Mixed line-entry and braced-entry syntax\nGOODKEY: good value\n{:good-key: good value}",
{"GOODKEY": "good value", "good-key": "good value"},
),
("Note without any key-value pairs", {}),
(
"Other text\nstandard_citation: doi:10/ckcj\nMore other text",
{"standard_citation": "doi:10/ckcj"},
),
],
)
def test_csl_item_note_dict(note, dictionary):
csl_item = CSL_Item(note=note)
assert csl_item.note_dict == dictionary
@pytest.mark.parametrize(
["date", "expected"],
[
(None, None),
("", None),
("2019", [2019]),
("2019-01", [2019, 1]),
("2019-12", [2019, 12]),
("2019-12-31", [2019, 12, 31]),
("2019-12-99", [2019, 12]),
("2019-12-01", [2019, 12, 1]),
(" 2019-12-01 ", [2019, 12, 1]),
("2019-12-30T23:32:16Z", [2019, 12, 30]),
(datetime.date(2019, 12, 31), [2019, 12, 31]),
(datetime.datetime(2019, 12, 31, 23, 32, 16), [2019, 12, 31]),
],
)
def test_date_to_date_parts(date, expected):
assert date_to_date_parts(date) == expected
@pytest.mark.parametrize(
["expected", "date_parts", "fill"],
[
(None, None, False),
(None, [], True),
(None, [], False),
(None, None, True),
("2019", [2019], False),
("2019-01-01", [2019], True),
("2019-01", [2019, 1], False),
("2019-12", [2019, 12], False),
("2019-12-01", [2019, 12], True),
("2019-12-31", [2019, 12, 31], False),
("2019-12-31", [2019, 12, 31], True),
("2019-12", [2019, 12, "bad day"], False),
("2019-12-01", [2019, 12, 1], False),
("2019-12-01", ["2019", "12", "01"], False),
("2019-02-01", ["2019", "2", "1"], False),
("2019-12-31", [2019, 12, 31, 23, 32, 16], False),
("2019-12-31", [2019, 12, 31, 23, 32, 16], True),
("0080-07-14", [80, 7, 14], False),
("0080-07-14", ["80", "07", 14], False),
],
)
def test_date_parts_to_string(expected, date_parts, fill):
assert expected == date_parts_to_string(date_parts, fill=fill)
Functions
test_assert_csl_item_type_passes
def test_assert_csl_item_type_passes(
)
View Source
def test_assert_csl_item_type_passes():
assert_csl_item_type(CSL_Item())
test_assert_csl_item_type_raises_error_on_dict
def test_assert_csl_item_type_raises_error_on_dict(
)
View Source
def test_assert_csl_item_type_raises_error_on_dict():
with pytest.raises(TypeError):
assert_csl_item_type({})
test_csl_item_note_append
def test_csl_item_note_append(
input_note,
text,
dictionary,
expected_note
)
View Source
@pytest.mark.parametrize(
["input_note", "text", "dictionary", "expected_note"],
[
("", "", {}, ""),
(None, "", {}, ""),
("preexisting note", "", {}, "preexisting note"),
(
"preexisting note",
"",
{"key": "the value"},
"preexisting note\nkey: the value",
),
("", "", {"KEYOKAY": "the value"}, "KEYOKAY: the value"),
("preexisting note", "", {"KEY-NOT-OKAY": "the value"}, "preexisting note"),
(
"",
"",
{"standard_citation": "doi:10.7554/elife.32822"},
"standard_citation: doi:10.7554/elife.32822",
),
(
"This CSL Item was produced using Manubot.",
"",
{"standard_citation": "doi:10.7554/elife.32822"},
"This CSL Item was produced using Manubot.\nstandard_citation: doi:10.7554/elife.32822",
),
# do not append duplicate lines to a note
# https://github.com/manubot/manubot/issues/258
("Already exists.", "Already exists.", {}, "Already exists."),
("", "exists: yes", {"exists": "yes"}, "exists: yes"),
],
)
def test_csl_item_note_append(input_note, text, dictionary, expected_note):
csl_item = CSL_Item({"id": "test_csl_item", "type": "entry", "note": input_note})
csl_item.note_append_text(text)
csl_item.note_append_dict(dictionary)
assert csl_item.note == expected_note
test_csl_item_note_dict
def test_csl_item_note_dict(
note,
dictionary
)
View Source
@pytest.mark.parametrize(
["note", "dictionary"],
[
(
"This is a note\nkey_one: value\nKEYTWO: value 2 ",
{"key_one": "value", "KEYTWO": "value 2"},
),
("BAD_KEY: good value\ngood-key: good value", {"good-key": "good value"}),
(
"This is a note {:key_one: value} {:KEYTWO: value 2 } ",
{"key_one": "value", "KEYTWO": "value 2"},
),
("{:BAD_KEY: good value}\n{:good-key: good value}", {"good-key": "good value"}),
(
"Mixed line-entry and braced-entry syntax\nGOODKEY: good value\n{:good-key: good value}",
{"GOODKEY": "good value", "good-key": "good value"},
),
("Note without any key-value pairs", {}),
(
"Other text\nstandard_citation: doi:10/ckcj\nMore other text",
{"standard_citation": "doi:10/ckcj"},
),
],
)
def test_csl_item_note_dict(note, dictionary):
csl_item = CSL_Item(note=note)
assert csl_item.note_dict == dictionary
test_csl_item_standardize_id
def test_csl_item_standardize_id(
csl_item,
standard_citation
)
View Source
@pytest.mark.parametrize(
["csl_item", "standard_citation"],
[
pytest.param(
{"id": "my-id", "standard_citation": "doi:10.7554/elife.32822"},
"doi:10.7554/elife.32822",
id="from_standard_citation",
),
pytest.param(
{"id": "doi:10.7554/elife.32822"},
"doi:10.7554/elife.32822",
id="from_doi_id",
),
pytest.param(
{"id": "DOI:10.7554/ELIFE.32822"},
"doi:10.7554/elife.32822",
id="from_doi_id_standardize",
),
pytest.param({"id": "my-id"}, "my-id", id="from_raw_id"),
],
)
def test_csl_item_standardize_id(csl_item, standard_citation):
csl_item = CSL_Item(csl_item)
output = csl_item.standardize_id()
assert output is csl_item
assert output["id"] == standard_citation
test_csl_item_standardize_id_note
def test_csl_item_standardize_id_note(
)
Test extracting standard_id from a note and setting additional
note fields.
View Source
def test_csl_item_standardize_id_note():
"""
Test extracting standard_id from a note and setting additional
note fields.
"""
csl_item = CSL_Item(
{
"id": "original-id",
"type": "article-journal",
"note": "standard_id: doi:10.1371/journal.PPAT.1006256",
}
)
csl_item.standardize_id()
assert csl_item["id"] == "doi:10.1371/journal.ppat.1006256"
note_dict = csl_item.note_dict
assert note_dict["original_id"] == "original-id"
assert note_dict["original_standard_id"] == "doi:10.1371/journal.PPAT.1006256"
test_csl_item_standardize_id_repeated
def test_csl_item_standardize_id_repeated(
)
View Source
def test_csl_item_standardize_id_repeated():
csl_item = CSL_Item(id="pmid:1", type="article-journal")
csl_item_1 = copy.deepcopy(csl_item.standardize_id())
assert "standard_citation" not in "csl_item"
csl_item_2 = copy.deepcopy(csl_item.standardize_id())
assert csl_item_1 == csl_item_2
test_date_parts_to_string
def test_date_parts_to_string(
expected,
date_parts,
fill
)
View Source
@pytest.mark.parametrize(
["expected", "date_parts", "fill"],
[
(None, None, False),
(None, [], True),
(None, [], False),
(None, None, True),
("2019", [2019], False),
("2019-01-01", [2019], True),
("2019-01", [2019, 1], False),
("2019-12", [2019, 12], False),
("2019-12-01", [2019, 12], True),
("2019-12-31", [2019, 12, 31], False),
("2019-12-31", [2019, 12, 31], True),
("2019-12", [2019, 12, "bad day"], False),
("2019-12-01", [2019, 12, 1], False),
("2019-12-01", ["2019", "12", "01"], False),
("2019-02-01", ["2019", "2", "1"], False),
("2019-12-31", [2019, 12, 31, 23, 32, 16], False),
("2019-12-31", [2019, 12, 31, 23, 32, 16], True),
("0080-07-14", [80, 7, 14], False),
("0080-07-14", ["80", "07", 14], False),
],
)
def test_date_parts_to_string(expected, date_parts, fill):
assert expected == date_parts_to_string(date_parts, fill=fill)
test_date_to_date_parts
def test_date_to_date_parts(
date,
expected
)
View Source
@pytest.mark.parametrize(
["date", "expected"],
[
(None, None),
("", None),
("2019", [2019]),
("2019-01", [2019, 1]),
("2019-12", [2019, 12]),
("2019-12-31", [2019, 12, 31]),
("2019-12-99", [2019, 12]),
("2019-12-01", [2019, 12, 1]),
(" 2019-12-01 ", [2019, 12, 1]),
("2019-12-30T23:32:16Z", [2019, 12, 30]),
(datetime.date(2019, 12, 31), [2019, 12, 31]),
(datetime.datetime(2019, 12, 31, 23, 32, 16), [2019, 12, 31]),
],
)
def test_date_to_date_parts(date, expected):
assert date_to_date_parts(date) == expected
Classes
Test_CSL_Item
class Test_CSL_Item(
/,
*args,
**kwargs
)
View Source
class Test_CSL_Item:
def test_constuctor_empty(self):
assert CSL_Item() == {}
def test_constuctor_by_dict(self):
d = {"title": "My book"}
assert CSL_Item(d) == d
def test_constuctor_by_keyword(self):
assert CSL_Item(type="journal-article") == {"type": "journal-article"}
def test_constuctor_by_dict_keyword_combination(self):
assert CSL_Item({"title": "My journal article"}, type="journal-article") == {
"title": "My journal article",
"type": "journal-article",
}
def test_recursive_constructor(self):
assert CSL_Item(CSL_Item()) == {}
assert CSL_Item(CSL_Item(abc=1)) == {"abc": 1}
def test_constructor_leaves_no_inplace_effects(self):
dict1 = {"a": 1}
ci = CSL_Item(dict1, b=2)
assert ci == {"a": 1, "b": 2}
assert dict1 == {"a": 1}
def test_correct_invalid_type(self):
assert CSL_Item(type="journal-article").correct_invalid_type() == {
"type": "article-journal"
}
def test_set_default_type(self):
assert CSL_Item().set_default_type() == {"type": "entry"}
def test_no_change_of_type(self):
assert CSL_Item(type="book").correct_invalid_type() == {"type": "book"}
assert CSL_Item(type="book").set_default_type() == {"type": "book"}
def test_clean(self):
csl_item = CSL_Item(type="chapter", id="abc")
csl_item.clean(prune=True)
assert csl_item == {"type": "chapter", "id": "abc"}
def test_clean_set_id(self):
csl_item = CSL_Item(type="chapter")
csl_item.set_id("abc")
csl_item.clean(prune=True)
assert csl_item == {"type": "chapter", "id": "abc"}
Methods
test_clean
def test_clean(
self
)
View Source
def test_clean(self):
csl_item = CSL_Item(type="chapter", id="abc")
csl_item.clean(prune=True)
assert csl_item == {"type": "chapter", "id": "abc"}
test_clean_set_id
def test_clean_set_id(
self
)
View Source
def test_clean_set_id(self):
csl_item = CSL_Item(type="chapter")
csl_item.set_id("abc")
csl_item.clean(prune=True)
assert csl_item == {"type": "chapter", "id": "abc"}
test_constructor_leaves_no_inplace_effects
def test_constructor_leaves_no_inplace_effects(
self
)
View Source
def test_constructor_leaves_no_inplace_effects(self):
dict1 = {"a": 1}
ci = CSL_Item(dict1, b=2)
assert ci == {"a": 1, "b": 2}
assert dict1 == {"a": 1}
test_constuctor_by_dict
def test_constuctor_by_dict(
self
)
View Source
def test_constuctor_by_dict(self):
d = {"title": "My book"}
assert CSL_Item(d) == d
test_constuctor_by_dict_keyword_combination
def test_constuctor_by_dict_keyword_combination(
self
)
View Source
def test_constuctor_by_dict_keyword_combination(self):
assert CSL_Item({"title": "My journal article"}, type="journal-article") == {
"title": "My journal article",
"type": "journal-article",
}
test_constuctor_by_keyword
def test_constuctor_by_keyword(
self
)
View Source
def test_constuctor_by_keyword(self):
assert CSL_Item(type="journal-article") == {"type": "journal-article"}
test_constuctor_empty
def test_constuctor_empty(
self
)
View Source
def test_constuctor_empty(self):
assert CSL_Item() == {}
test_correct_invalid_type
def test_correct_invalid_type(
self
)
View Source
def test_correct_invalid_type(self):
assert CSL_Item(type="journal-article").correct_invalid_type() == {
"type": "article-journal"
}
test_no_change_of_type
def test_no_change_of_type(
self
)
View Source
def test_no_change_of_type(self):
assert CSL_Item(type="book").correct_invalid_type() == {"type": "book"}
assert CSL_Item(type="book").set_default_type() == {"type": "book"}
test_recursive_constructor
def test_recursive_constructor(
self
)
View Source
def test_recursive_constructor(self):
assert CSL_Item(CSL_Item()) == {}
assert CSL_Item(CSL_Item(abc=1)) == {"abc": 1}
test_set_default_type
def test_set_default_type(
self
)
View Source
def test_set_default_type(self):
assert CSL_Item().set_default_type() == {"type": "entry"}