2019-03-11 17:28:34 +03:00
|
|
|
|
import pytest
|
|
|
|
|
from spacy import displacy
|
2020-08-21 12:51:31 +03:00
|
|
|
|
from spacy.displacy.render import DependencyRenderer, EntityRenderer
|
2020-09-21 21:43:54 +03:00
|
|
|
|
from spacy.tokens import Span, Doc
|
2019-03-11 20:52:50 +03:00
|
|
|
|
from spacy.lang.fa import Persian
|
2019-03-11 17:28:34 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_displacy_parse_ents(en_vocab):
|
|
|
|
|
"""Test that named entities on a Doc are converted into displaCy's format."""
|
2020-09-21 21:43:54 +03:00
|
|
|
|
doc = Doc(en_vocab, words=["But", "Google", "is", "starting", "from", "behind"])
|
2019-03-11 17:28:34 +03:00
|
|
|
|
doc.ents = [Span(doc, 1, 2, label=doc.vocab.strings["ORG"])]
|
|
|
|
|
ents = displacy.parse_ents(doc)
|
|
|
|
|
assert isinstance(ents, dict)
|
|
|
|
|
assert ents["text"] == "But Google is starting from behind "
|
|
|
|
|
assert ents["ents"] == [{"start": 4, "end": 10, "label": "ORG"}]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_displacy_parse_deps(en_vocab):
|
|
|
|
|
"""Test that deps and tags on a Doc are converted into displaCy's format."""
|
|
|
|
|
words = ["This", "is", "a", "sentence"]
|
2020-09-21 21:43:54 +03:00
|
|
|
|
heads = [1, 1, 3, 1]
|
2019-03-11 17:28:34 +03:00
|
|
|
|
pos = ["DET", "VERB", "DET", "NOUN"]
|
|
|
|
|
tags = ["DT", "VBZ", "DT", "NN"]
|
|
|
|
|
deps = ["nsubj", "ROOT", "det", "attr"]
|
2020-09-21 21:43:54 +03:00
|
|
|
|
doc = Doc(en_vocab, words=words, heads=heads, pos=pos, tags=tags, deps=deps)
|
2019-03-11 17:28:34 +03:00
|
|
|
|
deps = displacy.parse_deps(doc)
|
|
|
|
|
assert isinstance(deps, dict)
|
|
|
|
|
assert deps["words"] == [
|
2020-03-02 13:49:28 +03:00
|
|
|
|
{"lemma": None, "text": words[0], "tag": pos[0]},
|
|
|
|
|
{"lemma": None, "text": words[1], "tag": pos[1]},
|
|
|
|
|
{"lemma": None, "text": words[2], "tag": pos[2]},
|
|
|
|
|
{"lemma": None, "text": words[3], "tag": pos[3]},
|
2019-03-11 17:28:34 +03:00
|
|
|
|
]
|
|
|
|
|
assert deps["arcs"] == [
|
|
|
|
|
{"start": 0, "end": 1, "label": "nsubj", "dir": "left"},
|
|
|
|
|
{"start": 2, "end": 3, "label": "det", "dir": "left"},
|
|
|
|
|
{"start": 1, "end": 3, "label": "attr", "dir": "right"},
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
2019-08-20 16:51:37 +03:00
|
|
|
|
def test_displacy_invalid_arcs():
|
|
|
|
|
renderer = DependencyRenderer()
|
|
|
|
|
words = [{"text": "This", "tag": "DET"}, {"text": "is", "tag": "VERB"}]
|
|
|
|
|
arcs = [
|
|
|
|
|
{"start": 0, "end": 1, "label": "nsubj", "dir": "left"},
|
|
|
|
|
{"start": -1, "end": 2, "label": "det", "dir": "left"},
|
|
|
|
|
]
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
|
renderer.render([{"words": words, "arcs": arcs}])
|
|
|
|
|
|
|
|
|
|
|
2019-03-11 17:28:34 +03:00
|
|
|
|
def test_displacy_spans(en_vocab):
|
|
|
|
|
"""Test that displaCy can render Spans."""
|
2020-09-21 21:43:54 +03:00
|
|
|
|
doc = Doc(en_vocab, words=["But", "Google", "is", "starting", "from", "behind"])
|
2019-03-11 17:28:34 +03:00
|
|
|
|
doc.ents = [Span(doc, 1, 2, label=doc.vocab.strings["ORG"])]
|
|
|
|
|
html = displacy.render(doc[1:4], style="ent")
|
|
|
|
|
assert html.startswith("<div")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_displacy_raises_for_wrong_type(en_vocab):
|
|
|
|
|
with pytest.raises(ValueError):
|
|
|
|
|
displacy.render("hello world")
|
2019-03-11 20:52:50 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_displacy_rtl():
|
|
|
|
|
# Source: http://www.sobhe.ir/hazm/ – is this correct?
|
|
|
|
|
words = ["ما", "بسیار", "کتاب", "می\u200cخوانیم"]
|
|
|
|
|
# These are (likely) wrong, but it's just for testing
|
|
|
|
|
pos = ["PRO", "ADV", "N_PL", "V_SUB"] # needs to match lang.fa.tag_map
|
|
|
|
|
deps = ["foo", "bar", "foo", "baz"]
|
2020-09-21 21:43:54 +03:00
|
|
|
|
heads = [1, 0, 3, 1]
|
2019-03-11 20:52:50 +03:00
|
|
|
|
nlp = Persian()
|
2020-09-21 21:43:54 +03:00
|
|
|
|
doc = Doc(nlp.vocab, words=words, tags=pos, heads=heads, deps=deps)
|
2019-03-11 20:52:50 +03:00
|
|
|
|
doc.ents = [Span(doc, 1, 3, label="TEST")]
|
|
|
|
|
html = displacy.render(doc, page=True, style="dep")
|
|
|
|
|
assert "direction: rtl" in html
|
|
|
|
|
assert 'direction="rtl"' in html
|
2019-12-22 03:53:56 +03:00
|
|
|
|
assert f'lang="{nlp.lang}"' in html
|
2019-03-11 20:52:50 +03:00
|
|
|
|
html = displacy.render(doc, page=True, style="ent")
|
|
|
|
|
assert "direction: rtl" in html
|
2019-12-22 03:53:56 +03:00
|
|
|
|
assert f'lang="{nlp.lang}"' in html
|
2019-03-11 21:03:52 +03:00
|
|
|
|
|
2019-03-12 15:35:34 +03:00
|
|
|
|
|
2019-03-11 21:03:52 +03:00
|
|
|
|
def test_displacy_render_wrapper(en_vocab):
|
|
|
|
|
"""Test that displaCy accepts custom rendering wrapper."""
|
|
|
|
|
|
|
|
|
|
def wrapper(html):
|
|
|
|
|
return "TEST" + html + "TEST"
|
|
|
|
|
|
|
|
|
|
displacy.set_render_wrapper(wrapper)
|
2020-09-21 21:43:54 +03:00
|
|
|
|
doc = Doc(en_vocab, words=["But", "Google", "is", "starting", "from", "behind"])
|
2019-03-11 21:03:52 +03:00
|
|
|
|
doc.ents = [Span(doc, 1, 2, label=doc.vocab.strings["ORG"])]
|
|
|
|
|
html = displacy.render(doc, style="ent")
|
|
|
|
|
assert html.startswith("TEST<div")
|
|
|
|
|
assert html.endswith("/div>TEST")
|
2019-03-12 15:35:34 +03:00
|
|
|
|
# Restore
|
|
|
|
|
displacy.set_render_wrapper(lambda html: html)
|
2020-08-21 12:51:31 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_displacy_options_case():
|
|
|
|
|
ents = ["foo", "BAR"]
|
|
|
|
|
colors = {"FOO": "red", "bar": "green"}
|
|
|
|
|
renderer = EntityRenderer({"ents": ents, "colors": colors})
|
|
|
|
|
text = "abcd"
|
|
|
|
|
labels = ["foo", "bar", "FOO", "BAR"]
|
|
|
|
|
spans = [{"start": i, "end": i + 1, "label": labels[i]} for i in range(len(text))]
|
|
|
|
|
result = renderer.render_ents("abcde", spans, None).split("\n\n")
|
|
|
|
|
assert "red" in result[0] and "foo" in result[0]
|
|
|
|
|
assert "green" in result[1] and "bar" in result[1]
|
|
|
|
|
assert "red" in result[2] and "FOO" in result[2]
|
|
|
|
|
assert "green" in result[3] and "BAR" in result[3]
|