diff --git a/spacy/displacy/render.py b/spacy/displacy/render.py index 8e980d203..fb25b60e2 100644 --- a/spacy/displacy/render.py +++ b/spacy/displacy/render.py @@ -6,6 +6,8 @@ import uuid from .templates import TPL_DEP_SVG, TPL_DEP_WORDS, TPL_DEP_ARCS, TPL_ENTS from .templates import TPL_ENT, TPL_ENT_RTL, TPL_FIGURE, TPL_TITLE, TPL_PAGE from ..util import minify_html, escape_html, get_entry_points +from ..errors import Errors + DEFAULT_LANG = "en" DEFAULT_DIR = "ltr" @@ -124,6 +126,9 @@ class DependencyRenderer(object): i (int): Unique ID, typically arrow index. RETURNS (unicode): Rendered SVG markup. """ + if start < 0 or end < 0: + error_args = dict(start=start, end=end, label=label, dir=direction) + raise ValueError(Errors.E156.format(**error_args)) level = self.levels.index(end - start) + 1 x_start = self.offset_x + start * self.distance + self.arrow_spacing if self.direction == "rtl": diff --git a/spacy/errors.py b/spacy/errors.py index d23ad66e8..e8027f2cf 100644 --- a/spacy/errors.py +++ b/spacy/errors.py @@ -428,6 +428,10 @@ class Errors(object): E154 = ("Either the `nlp` model or the `vocab` should be specified.") E155 = ("The `nlp` object should have access to pre-trained word vectors, cf. " "https://spacy.io/usage/models#languages.") + E156 = ("Can't render negative values for dependency arc start or end. " + "Make sure that you're passing in absolute token indices, not " + "relative token offsets.\nstart: {start}, end: {end}, label: " + "{label}, direction: {dir}") @add_codes diff --git a/spacy/tests/test_displacy.py b/spacy/tests/test_displacy.py index 2097fd081..5e99d261a 100644 --- a/spacy/tests/test_displacy.py +++ b/spacy/tests/test_displacy.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import pytest from spacy import displacy +from spacy.displacy.render import DependencyRenderer from spacy.tokens import Span from spacy.lang.fa import Persian @@ -42,6 +43,17 @@ def test_displacy_parse_deps(en_vocab): ] +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}]) + + def test_displacy_spans(en_vocab): """Test that displaCy can render Spans.""" doc = get_doc(en_vocab, words=["But", "Google", "is", "starting", "from", "behind"])