ja_sentence_segmenter.split.simple_splitter

Simple sentence splitter for japanese text.

  1"""Simple sentence splitter for japanese text."""
  2
  3import re
  4from collections.abc import Generator, Iterator
  5from re import Match
  6from typing import Union, overload
  7
  8BETWEEN_QUOTE_JA_REGEX = r"「[^「」]*」"
  9"""japanese quotation, whose punctuation is protected from splitting."""
 10
 11BETWEEN_PARENS_JA_REGEX = r"\([^()]*\)"
 12"""parentheses, whose punctuation is protected from splitting."""
 13
 14ESCAPE_CHAR = "∯"
 15"""sentinel wrapped around punctuation that must not split a sentence.
 16
 17it is stripped again once splitting is done. that final strip cannot tell a
 18sentinel apart from the same character in the input, so any U+222F already
 19present in the text is silently removed. remove it beforehand if your text
 20may contain it.
 21"""
 22
 23DEFAULT_PUNCTUATION_REGEX = r"。!?"
 24"""default punctuation characters for splitting."""
 25
 26
 27def __split_newline_iter(texts: Iterator[str]) -> Generator[str, None, None]:
 28    for text in texts:
 29        yield from text.splitlines()
 30
 31
 32@overload
 33def split_newline(arg: str) -> Generator[str, None, None]: ...
 34
 35
 36@overload
 37def split_newline(arg: list[str]) -> Generator[str, None, None]: ...
 38
 39
 40@overload
 41def split_newline(arg: Iterator[str]) -> Generator[str, None, None]: ...
 42
 43
 44def split_newline(arg: Union[str, list[str], Iterator[str]]) -> Generator[str, None, None]:
 45    """Split text with line boundaries.
 46
 47    Parameters
 48    ----------
 49    arg : Union[str, List[str], Iterator[str]]
 50        texts you want to split.
 51
 52    Yields
 53    ------
 54    Generator[str, None, None]
 55        texts splitted with line boundaries.
 56    """
 57    if isinstance(arg, str):
 58        yield from __split_newline_iter(iter([arg]))
 59    elif isinstance(arg, list):
 60        yield from __split_newline_iter(iter(arg))
 61    elif isinstance(arg, Iterator):
 62        yield from __split_newline_iter(arg)
 63
 64
 65def __split_punctuation_iter(texts: Iterator[str], punctuations: str, split_between_quote: bool, split_between_parens: bool) -> Generator[str, None, None]:
 66    def escape_between_punctuation(match: Match[str]) -> str:
 67        text = match.group()
 68        escape_regex = rf"(?<!{ESCAPE_CHAR})([{punctuations}])(?!{ESCAPE_CHAR})"
 69        result = re.sub(escape_regex, rf"{ESCAPE_CHAR}\1{ESCAPE_CHAR}", text)
 70        return result
 71
 72    def escape_between_quote(text: str) -> str:
 73        result = re.sub(BETWEEN_QUOTE_JA_REGEX, escape_between_punctuation, text)
 74        return result
 75
 76    def escape_between_parens(text: str) -> str:
 77        result = re.sub(BETWEEN_PARENS_JA_REGEX, escape_between_punctuation, text)
 78        return result
 79
 80    def sub_split_punctuation(text: str) -> list[str]:
 81        split_regex = rf"(?<!{ESCAPE_CHAR})([{punctuations}])(?!{ESCAPE_CHAR})"
 82        result = re.sub(split_regex, "\\1\n", text)
 83        unescape_regex = rf"({ESCAPE_CHAR})([{punctuations}])({ESCAPE_CHAR})"
 84        result = re.sub(unescape_regex, "\\2", result)
 85        return result.splitlines()
 86
 87    for text in texts:
 88        temp = text
 89        if not split_between_quote:
 90            temp = escape_between_quote(temp)
 91        if not split_between_parens:
 92            temp = escape_between_parens(temp)
 93        sentences = sub_split_punctuation(temp)
 94        yield from sentences
 95
 96
 97@overload
 98def split_punctuation(
 99    arg: str, punctuations: str = DEFAULT_PUNCTUATION_REGEX, split_between_quote: bool = False, split_between_parens: bool = False
100) -> Generator[str, None, None]: ...
101
102
103@overload
104def split_punctuation(
105    arg: list[str], punctuations: str = DEFAULT_PUNCTUATION_REGEX, split_between_quote: bool = False, split_between_parens: bool = False
106) -> Generator[str, None, None]: ...
107
108
109@overload
110def split_punctuation(
111    arg: Iterator[str], punctuations: str = DEFAULT_PUNCTUATION_REGEX, split_between_quote: bool = False, split_between_parens: bool = False
112) -> Generator[str, None, None]: ...
113
114
115def split_punctuation(
116    arg: Union[str, list[str], Iterator[str]],
117    punctuations: str = DEFAULT_PUNCTUATION_REGEX,
118    split_between_quote: bool = False,
119    split_between_parens: bool = False,
120) -> Generator[str, None, None]:
121    """Split text with puctuations.
122
123    Parameters
124    ----------
125    arg : Union[str, List[str], Iterator[str]]
126        texts you want to split
127    punctuations : str, optional
128        regular expression for puctuations, by default DEFAULT_PUNCTUATION_REGEX
129    split_between_quote : bool, optional
130        split if punctuation between quotes, by default False
131    split_between_parens : bool, optional
132        split if punctuation between parentheses, by default False
133
134    Yields
135    ------
136    Generator[str, None, None]
137        texts splitted with puctuations.
138
139    Notes
140    -----
141    protecting punctuation inside quotes and parentheses is implemented by
142    wrapping it in ESCAPE_CHAR (U+222F) and stripping that again afterwards.
143    the strip cannot tell a sentinel apart from the same character in the
144    input, so any U+222F already present in the text is silently removed.
145    """
146    if isinstance(arg, str):
147        yield from __split_punctuation_iter(iter([arg]), punctuations, split_between_quote, split_between_parens)
148    elif isinstance(arg, list):
149        yield from __split_punctuation_iter(iter(arg), punctuations, split_between_quote, split_between_parens)
150    elif isinstance(arg, Iterator):
151        yield from __split_punctuation_iter(arg, punctuations, split_between_quote, split_between_parens)
BETWEEN_QUOTE_JA_REGEX = '「[^「」]*」'

japanese quotation, whose punctuation is protected from splitting.

BETWEEN_PARENS_JA_REGEX = '\\([^()]*\\)'

parentheses, whose punctuation is protected from splitting.

ESCAPE_CHAR = '∯'

sentinel wrapped around punctuation that must not split a sentence.

it is stripped again once splitting is done. that final strip cannot tell a sentinel apart from the same character in the input, so any U+222F already present in the text is silently removed. remove it beforehand if your text may contain it.

DEFAULT_PUNCTUATION_REGEX = '。!?'

default punctuation characters for splitting.

def split_newline(arg: Union[str, list[str], Iterator[str]]) -> Generator[str, None, None]:
45def split_newline(arg: Union[str, list[str], Iterator[str]]) -> Generator[str, None, None]:
46    """Split text with line boundaries.
47
48    Parameters
49    ----------
50    arg : Union[str, List[str], Iterator[str]]
51        texts you want to split.
52
53    Yields
54    ------
55    Generator[str, None, None]
56        texts splitted with line boundaries.
57    """
58    if isinstance(arg, str):
59        yield from __split_newline_iter(iter([arg]))
60    elif isinstance(arg, list):
61        yield from __split_newline_iter(iter(arg))
62    elif isinstance(arg, Iterator):
63        yield from __split_newline_iter(arg)

Split text with line boundaries.

Parameters
  • arg (Union[str, List[str], Iterator[str]]): texts you want to split.
Yields
  • Generator[str, None, None]: texts splitted with line boundaries.
def split_punctuation( arg: Union[str, list[str], Iterator[str]], punctuations: str = '。!?', split_between_quote: bool = False, split_between_parens: bool = False) -> Generator[str, None, None]:
116def split_punctuation(
117    arg: Union[str, list[str], Iterator[str]],
118    punctuations: str = DEFAULT_PUNCTUATION_REGEX,
119    split_between_quote: bool = False,
120    split_between_parens: bool = False,
121) -> Generator[str, None, None]:
122    """Split text with puctuations.
123
124    Parameters
125    ----------
126    arg : Union[str, List[str], Iterator[str]]
127        texts you want to split
128    punctuations : str, optional
129        regular expression for puctuations, by default DEFAULT_PUNCTUATION_REGEX
130    split_between_quote : bool, optional
131        split if punctuation between quotes, by default False
132    split_between_parens : bool, optional
133        split if punctuation between parentheses, by default False
134
135    Yields
136    ------
137    Generator[str, None, None]
138        texts splitted with puctuations.
139
140    Notes
141    -----
142    protecting punctuation inside quotes and parentheses is implemented by
143    wrapping it in ESCAPE_CHAR (U+222F) and stripping that again afterwards.
144    the strip cannot tell a sentinel apart from the same character in the
145    input, so any U+222F already present in the text is silently removed.
146    """
147    if isinstance(arg, str):
148        yield from __split_punctuation_iter(iter([arg]), punctuations, split_between_quote, split_between_parens)
149    elif isinstance(arg, list):
150        yield from __split_punctuation_iter(iter(arg), punctuations, split_between_quote, split_between_parens)
151    elif isinstance(arg, Iterator):
152        yield from __split_punctuation_iter(arg, punctuations, split_between_quote, split_between_parens)

Split text with puctuations.

Parameters
  • arg (Union[str, List[str], Iterator[str]]): texts you want to split
  • punctuations (str, optional): regular expression for puctuations, by default DEFAULT_PUNCTUATION_REGEX
  • split_between_quote (bool, optional): split if punctuation between quotes, by default False
  • split_between_parens (bool, optional): split if punctuation between parentheses, by default False
Yields
  • Generator[str, None, None]: texts splitted with puctuations.
Notes

protecting punctuation inside quotes and parentheses is implemented by wrapping it in ESCAPE_CHAR (U+222F) and stripping that again afterwards. the strip cannot tell a sentinel apart from the same character in the input, so any U+222F already present in the text is silently removed.