Skip to content

Commit 5e82adc

Browse files
Bram VanroyBram Vanroy
authored andcommitted
fix pretokenized input format
Now, a list of tokens is not valid input anymore
1 parent 8bfe62b commit 5e82adc

6 files changed

Lines changed: 38 additions & 52 deletions

File tree

HISTORY.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
# History
22

3+
## 3.3.0 (January 17th, 2023)
4+
5+
Since spaCy 3.2.0, the data that is passed to a spaCy pipeline has become more strict. This means that passing
6+
a list of pretokenized tokens (`["This", "is", "a", "pretokenized", "sentence"]`) is not accepted anymore. Therefore,
7+
the `is_tokenized` option needed to be adapted to reflect this. It is still possible to pass a string where tokens
8+
are separated by whitespaces, e.g. `"This is a pretokenized sentence"`, which will continue to work for spaCy and
9+
stanza. Support for pretokenized data has been dropped for UDPipe.
10+
11+
Specific changes:
12+
13+
- **[conllparser]** Breaking change: `is_tokenized` is not a valid argument to `ConllParser` any more.
14+
- **[utils/conllparser]** Breaking change: when using UDPipe, pretokenized data is not supported any more.
15+
- **[utils]** Breaking change: `SpacyPretokenizedTokenizer.__call__` does not support a list of tokens any more.
16+
317
## 3.2.0 (April 4th, 2022)
418

519
- **[conllformatter]** Fixed an issue where `SpaceAfter=No` was not added correctly to tokens

README.md

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
# Parsing to CoNLL with spaCy, spacy-stanza, and spacy-udpipe
22

3-
**The last version to support spaCy v2 can be found** [here](<https://github.com/BramVanroy/spacy_conll/tree/v2.1.0>).
4-
The current version only supports v3.
5-
6-
This module allows you to parse text into CoNLL-U format\_. You can use it as a command line tool, or embed it in your
3+
This module allows you to parse text into CoNLL-U format. You can use it as a command line tool, or embed it in your
74
own scripts by adding it as a custom pipeline component to a spaCy, `spacy-stanza`, or `spacy-udpipe` pipeline. It
85
also provides an easy-to-use function to quickly initialize a parser as well as a ConllParser class with built-in
96
functionality to parse files or text.
@@ -26,23 +23,22 @@ By default, this package automatically installs only [spaCy](https://spacy.io/us
2623
*are* trained on UD data.
2724

2825
**NOTE**: `spacy-stanza` and `spacy-udpipe` are not installed automatically as a dependency for this library, because
29-
it might be too much overhead for those who don't need UD. If you wish to use their functionality (e.g. better
30-
performance, real UD output), you have to install them manually or use one of the available options as described
31-
below.
26+
it might be too much overhead for those who don't need UD. If you wish to use their functionality, you have to install
27+
them manually or use one of the available options as described below.
3228

3329
If you want to retrieve CoNLL info as a `pandas` DataFrame, this library will automatically export it if it detects
3430
that `pandas` is installed. See the Usage section for more.
3531

3632
To install the library, simply use pip.
3733

38-
```bash
34+
```shell
3935
# only includes spacy by default
4036
pip install spacy_conll
4137
```
4238

4339
A number of options are available to make installation of additional dependencies easier:
4440

45-
```bash
41+
```shell
4642
# include spacy-stanza and spacy-udpipe
4743
pip install spacy_conll[parsers]
4844
# include pandas
@@ -100,11 +96,8 @@ Because this library supports different spaCy wrappers (`spacy`, `stanza`, and `
10096
find the function's signature below. Have a look at the [source code](spacy_conll/utils.py) to read more about all the
10197
possible arguments or try out the [examples](examples/).
10298

103-
**NOTE**: `is_tokenized` does not work for `spacy-udpipe` and `disable_sbd` only works for `spacy`. `spacy-udpipe` has
104-
made a change to allow pretokenized text, but it depends on the input format and cannot be fixed at initialisation of
105-
the parser. See release v0.3.0 of spacy-udpipe or [this PR](https://github.com/TakeLab/spacy-udpipe/pull/19). Using
106-
`is_tokenized` for `spacy-stanza` also affects sentence segmentation, effectively *only* splitting on new
107-
lines. With `spacy`, `is_tokenized` disables sentence splitting completely.
99+
**NOTE**: `is_tokenized` does not work for `spacy-udpipe`. Using `is_tokenized` for `spacy-stanza` also affects sentence
100+
segmentation, effectively *only* splitting on new lines. With `spacy`, `is_tokenized` disables sentence splitting completely.
108101

109102
```python
110103
def init_parser(
@@ -221,8 +214,8 @@ for sent in doc.sents:
221214
Upon installation, a command-line script is added under tha alias `parse-as-conll`. You can use it to parse a
222215
string or file into CoNLL format given a number of options.
223216

224-
```bash
225-
> parse-as-conll -h
217+
```shell
218+
parse-as-conll -h
226219
usage: parse-as-conll [-h] [-f INPUT_FILE] [-a INPUT_ENCODING] [-b INPUT_STR] [-o OUTPUT_FILE]
227220
[-c OUTPUT_ENCODING] [-s] [-t] [-d] [-e] [-j N_PROCESS] [-v]
228221
[--ignore_pipe_errors] [--no_split_on_newline]
@@ -295,8 +288,8 @@ optional arguments:
295288
296289
For example, parsing a single line, multi-sentence string:
297290
298-
```bash
299-
> parse-as-conll en_core_web_sm spacy --input_str "I like cookies. What about you?" --include_headers
291+
```shell
292+
parse-as-conll en_core_web_sm spacy --input_str "I like cookies. What about you?" --include_headers
300293
301294
# sent_id = 1
302295
# text = I like cookies.
@@ -315,8 +308,8 @@ For example, parsing a single line, multi-sentence string:
315308
316309
For example, parsing a large input file and writing output to a given output file, using four processes:
317310
318-
```bash
319-
> parse-as-conll en_core_web_sm spacy --input_file large-input.txt --output_file large-conll-output.txt --include_headers --disable_sbd -j 4
311+
```shell
312+
parse-as-conll en_core_web_sm spacy --input_file large-input.txt --output_file large-conll-output.txt --include_headers --disable_sbd -j 4
320313
```
321314
322315

spacy_conll/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "3.2.0"
1+
__version__ = "3.3.0"
22

33
from .formatter import ConllFormatter
44
from .parser import ConllParser

spacy_conll/parser.py

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,9 @@ class ConllParser:
2929
3030
Constructor arguments:
3131
:param nlp: instantiated spaCy-like parser
32-
:param is_tokenized: whether or not the expected input format is pre-tokenized. This must correspond with how
33-
'nlp' was initialized! If you initialized the 'nlp' object with 'init_parser', make sure you used 'is_tokenized'
34-
in the same way
3532
"""
3633

3734
nlp: Language
38-
is_tokenized: bool = False
3935
parser: str = field(init=False, default=None)
4036

4137
def __post_init__(self):
@@ -56,21 +52,7 @@ def __post_init__(self):
5652
self.parser = "spacy"
5753

5854
def __repr__(self) -> str:
59-
return f"{self.__class__.__name__}(is_tokenized={self.is_tokenized}, parser={self.parser})"
60-
61-
def prepare_data(self, lines: List[str]) -> List[str]:
62-
"""Prepares data according to whether or not is_tokenized was given and depending on the parser.
63-
Each parser requires a different type of input when the data is pre_tokenized.
64-
:param lines: a list of lines to process
65-
:return: the lines in the correct format for the parser
66-
"""
67-
if self.is_tokenized:
68-
if self.parser == "spacy":
69-
lines = [l.split() for l in lines]
70-
elif self.parser == "udpipe":
71-
lines = [[l.split()] for l in lines]
72-
73-
return lines
55+
return f"{self.__class__.__name__}(parser={self.parser})"
7456

7557
def parse_file_as_conll(
7658
self, input_file: Union[PathLike, Path, str], input_encoding: str = getpreferredencoding(), **kwargs
@@ -128,8 +110,6 @@ def parse_text_as_conll(
128110
else:
129111
text = text.splitlines()
130112

131-
text = self.prepare_data(text)
132-
133113
conll_idx = 0
134114
output = ""
135115
for doc_idx, doc in enumerate(self.nlp.pipe(text, n_process=n_process)):

spacy_conll/utils.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def init_parser(
5151
See the stanza documentation for more:
5252
https://stanfordnlp.github.io/stanza/tokenize.html#start-with-pretokenized-text
5353
54-
This option does not affect UDPipe.
54+
This option is not supported in UDPipe.
5555
:param disable_sbd: disables automatic sentence boundary detection in spaCy and stanza. For stanza, make sure that
5656
your input is in the correct format, that is: sentences must be separated by two new lines. If you want to
5757
disable both tokenization and sentence segmentation in stanza, do not enable this option but instead only
@@ -60,7 +60,7 @@ def init_parser(
6060
See the stanza documentation for more:
6161
https://stanfordnlp.github.io/stanza/tokenize.html#tokenization-without-sentence-segmentation
6262
63-
This option does not affect UDPipe.
63+
This option is not supported in UDPipe.
6464
:param exclude_spacy_components: spaCy components to exclude from the pipeline, which can greatly improve
6565
processing speed. Only works when using spaCy as a parser.
6666
:param parser_opts: will be passed to the core pipeline. For spacy, it will be passed to its
@@ -133,19 +133,17 @@ def __init__(self, vocab: Vocab):
133133
"""
134134
self.vocab = vocab
135135

136-
def __call__(self, inp: Union[List[str], str]) -> Doc:
136+
def __call__(self, inp: str) -> Doc:
137137
"""Call the tokenizer on input `inp`.
138-
:param inp: either a string to be split on whitespace, or a list of tokens
138+
:param inp: a string to be split on whitespaces
139139
:return: the created Doc object
140140
"""
141141
if isinstance(inp, str):
142142
words = inp.split()
143143
spaces = [True] * (len(words) - 1) + ([True] if inp[-1].isspace() else [False])
144144
return Doc(self.vocab, words=words, spaces=spaces)
145-
elif isinstance(inp, list):
146-
return Doc(self.vocab, words=inp)
147145
else:
148-
raise ValueError("Unexpected input format. Expected string to be split on whitespace, or list of tokens.")
146+
raise ValueError("Unexpected input format. Expected string to be split on whitespace.")
149147

150148

151149
@Language.factory("disable_sbd")

tests/conftest.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ def conllparser(request):
5050
yield ConllParser(get_parser(request.param, include_headers=True))
5151

5252

53-
@pytest.fixture(params=["spacy", "stanza", "udpipe"])
53+
# Not testing with UDPipe, which does not support this
54+
@pytest.fixture(params=["spacy", "stanza"])
5455
def pretokenized_conllparser(request):
55-
yield ConllParser(get_parser(request.param, is_tokenized=True, include_headers=True), is_tokenized=True)
56+
yield ConllParser(get_parser(request.param, is_tokenized=True, include_headers=True))
5657

5758

5859
@pytest.fixture
@@ -101,7 +102,7 @@ def base_doc(base_parser, text):
101102
def pretokenized_doc(pretokenized_parser):
102103
name = pretokenized_parser[1]
103104
if name == "spacy":
104-
yield pretokenized_parser[0](single_sent().split())
105+
yield pretokenized_parser[0](single_sent())
105106
else:
106107
yield pretokenized_parser[0](single_sent())
107108

0 commit comments

Comments
 (0)