ts-tokenizer 0.2.2__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. {ts_tokenizer-0.2.2/ts_tokenizer.egg-info → ts_tokenizer-0.2.3}/PKG-INFO +1 -1
  2. ts_tokenizer-0.2.3/tests/test_abbr_apostrophe_suffix.py +30 -0
  3. ts_tokenizer-0.2.3/tests/test_abbreviation_lookup.py +13 -0
  4. ts_tokenizer-0.2.3/tests/test_currency_suffix.py +17 -0
  5. ts_tokenizer-0.2.3/tests/test_symbolic_marks.py +43 -0
  6. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/__init__.py +1 -1
  7. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/abbr_list.txt +2 -1
  8. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/cand_abbr_list.txt +1 -0
  9. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/currency_symbols.txt +1 -0
  10. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data.py +8 -1
  11. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/token_handler.py +66 -3
  12. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3/ts_tokenizer.egg-info}/PKG-INFO +1 -1
  13. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer.egg-info/SOURCES.txt +4 -0
  14. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/LICENSE +0 -0
  15. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/MANIFEST.in +0 -0
  16. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/README.md +0 -0
  17. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/pyproject.toml +0 -0
  18. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/setup.cfg +0 -0
  19. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/setup.py +0 -0
  20. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/tests/test_opening_quote_tokenization.py +0 -0
  21. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/char_fix.py +0 -0
  22. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/cli.py +0 -0
  23. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/TS_Corpus_Turkish_Word_List.txt +0 -0
  24. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/corection_mark.txt +0 -0
  25. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/domains.txt +0 -0
  26. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/emoticons.txt +0 -0
  27. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/eng_word_list.txt +0 -0
  28. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/exceptions.txt +0 -0
  29. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/data/smileys.txt +0 -0
  30. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/date_check.py +0 -0
  31. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/emoticon_check.py +0 -0
  32. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/inner_punc.py +0 -0
  33. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/punctuation_process.py +0 -0
  34. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/smiley_check.py +0 -0
  35. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/tokenizer.py +0 -0
  36. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer/unit_test.py +0 -0
  37. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer.egg-info/dependency_links.txt +0 -0
  38. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer.egg-info/entry_points.txt +0 -0
  39. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer.egg-info/requires.txt +0 -0
  40. {ts_tokenizer-0.2.2 → ts_tokenizer-0.2.3}/ts_tokenizer.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ts_tokenizer
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: TS Tokenizer is a hybrid (lexicon-based and rule-based) tokenizer designed specifically for tokenizing Turkish texts.
5
5
  Home-page: https://github.com/tanerim/ts_tokenizer
6
6
  Author: Taner Sezer
@@ -0,0 +1,30 @@
1
+ from ts_tokenizer.tokenizer import tokenize
2
+
3
+
4
+ def tagged_lines(text):
5
+ return [tuple(line.split("\t")) for line in tokenize(text, "tagged").splitlines()]
6
+
7
+
8
+ def test_candidate_abbr_with_apostrophe_suffix():
9
+ assert tagged_lines("md.'ye") == [
10
+ ("md.", "Abbr"),
11
+ ("'", "Punc"),
12
+ ("ye", "Valid_Word"),
13
+ ]
14
+
15
+
16
+ def test_sentence_fragment_with_ordinal_and_abbr_suffix():
17
+ assert tagged_lines("2. md.'ye") == [
18
+ ("2.", "Ordinal_Number"),
19
+ ("md.", "Abbr"),
20
+ ("'", "Punc"),
21
+ ("ye", "Valid_Word"),
22
+ ]
23
+
24
+
25
+ def test_existing_abbr_with_apostrophe_suffix():
26
+ assert tagged_lines("Prof.'a") == [
27
+ ("Prof.", "Abbr"),
28
+ ("'", "Punc"),
29
+ ("a", "OOV"),
30
+ ]
@@ -0,0 +1,13 @@
1
+ from ts_tokenizer.tokenizer import tokenize
2
+
3
+
4
+ def tagged_lines(text):
5
+ return [tuple(line.split("\t")) for line in tokenize(text, "tagged").splitlines()]
6
+
7
+
8
+ def test_uppercase_abbreviation_from_abbr_list():
9
+ assert tagged_lines("YHT") == [("YHT", "Abbr")]
10
+
11
+
12
+ def test_existing_abbreviation_behavior_is_preserved():
13
+ assert tagged_lines("TBMM'ye") == [("TBMM'ye", "Apostrophed")]
@@ -0,0 +1,17 @@
1
+ from ts_tokenizer.tokenizer import tokenize
2
+
3
+
4
+ def tagged_lines(text):
5
+ return [tuple(line.split("\t")) for line in tokenize(text, "tagged").splitlines()]
6
+
7
+
8
+ def test_currency_suffix_forms_are_preserved():
9
+ assert tagged_lines("₺350'lik") == [("₺350'lik", "Currency")]
10
+ assert tagged_lines("350₺'lik") == [("350₺'lik", "Currency")]
11
+ assert tagged_lines("$100'luk") == [("$100'luk", "Currency")]
12
+ assert tagged_lines("100$'lık") == [("100$'lık", "Currency")]
13
+
14
+
15
+ def test_plain_currency_forms_remain_unchanged():
16
+ assert tagged_lines("350₺") == [("350₺", "Currency")]
17
+ assert tagged_lines("₺350") == [("₺350", "Currency")]
@@ -0,0 +1,43 @@
1
+ from ts_tokenizer.tokenizer import tokenize
2
+
3
+
4
+ def tagged_lines(text):
5
+ return [tuple(line.split("\t")) for line in tokenize(text, "tagged").splitlines()]
6
+
7
+
8
+ def test_registered_mark_allows_underscored_words():
9
+ assert tagged_lines("yeni_firma®") == [
10
+ ("yeni_firma®", "Registered"),
11
+ ]
12
+ assert tagged_lines("eski_Firma®") == [
13
+ ("eski_Firma®", "Registered"),
14
+ ]
15
+
16
+
17
+ def test_existing_symbolic_mark_behavior_is_preserved():
18
+ assert tagged_lines("tscorpus®") == [("tscorpus®", "Registered")]
19
+ assert tagged_lines("abc™") == [("abc™", "Trademark")]
20
+ assert tagged_lines("©tscorpus") == [("©tscorpus", "Copyright")]
21
+
22
+
23
+ def test_symbolic_marks_with_trailing_punctuation_are_preserved():
24
+ assert tagged_lines("™kuruldu.") == [
25
+ ("™kuruldu", "Trademark"),
26
+ (".", "Punc"),
27
+ ]
28
+ assert tagged_lines("kapandı©.") == [
29
+ ("kapandı©", "Copyright"),
30
+ (".", "Punc"),
31
+ ]
32
+
33
+
34
+ def test_mixed_sentence_with_symbolic_marks():
35
+ assert tagged_lines("yeni_firma® ™kuruldu. eskiFirma® kapandı©. ®yepyeni") == [
36
+ ("yeni_firma®", "Registered"),
37
+ ("™kuruldu", "Trademark"),
38
+ (".", "Punc"),
39
+ ("eskiFirma®", "Registered"),
40
+ ("kapandı©", "Copyright"),
41
+ (".", "Punc"),
42
+ ("®yepyeni", "Registered"),
43
+ ]
@@ -1,6 +1,6 @@
1
1
  from importlib import import_module
2
2
 
3
- __version__ = "0.2.2"
3
+ __version__ = "0.2.3"
4
4
 
5
5
  _EXPORT_MAP = {
6
6
  "tokenize": (".tokenizer", "tokenize"),
@@ -1128,4 +1128,5 @@ ltd.
1128
1128
  s.s.c.b.
1129
1129
  http
1130
1130
  https
1131
- ftp
1131
+ ftp
1132
+ YHT
@@ -1,6 +1,8 @@
1
1
  import os
2
2
  from typing import FrozenSet
3
3
 
4
+ from .char_fix import CharFix
5
+
4
6
  base_dir = os.path.dirname(os.path.abspath(__file__))
5
7
  data_dir = os.path.join(base_dir, 'data')
6
8
 
@@ -8,7 +10,8 @@ data_dir = os.path.join(base_dir, 'data')
8
10
 
9
11
  emoticons = set(line.strip() for line in open(os.path.join(data_dir, 'emoticons.txt')))
10
12
  smileys = set(line.strip() for line in open(os.path.join(data_dir, 'smileys.txt')))
11
- abbrs = set(line.strip() for line in open(os.path.join(data_dir, 'abbr_list.txt')))
13
+ abbrs = set(CharFix.tr_lowercase(line.strip()) for line in open(os.path.join(data_dir, 'abbr_list.txt')))
14
+ candidate_abbrs = set(line.strip() for line in open(os.path.join(data_dir, 'cand_abbr_list.txt')))
12
15
  word_list = set(line.strip() for line in open(os.path.join(data_dir, 'TS_Corpus_Turkish_Word_List.txt')))
13
16
  exception_words = set(line.strip() for line in open(os.path.join(data_dir, 'exceptions.txt')))
14
17
  eng_words = set(line.strip() for line in open(os.path.join(data_dir, 'eng_word_list.txt')))
@@ -30,6 +33,10 @@ class LocalData:
30
33
  def abbrs():
31
34
  return abbrs
32
35
 
36
+ @staticmethod
37
+ def candidate_abbrs():
38
+ return candidate_abbrs
39
+
33
40
  @staticmethod
34
41
  def word_list():
35
42
  return word_list
@@ -23,6 +23,7 @@ REGEX_PATTERNS = {
23
23
  "hour": re.compile(r"^(0[0-9]|1[0-9]|2[0-3])[:.][0-5][0-9]$"),
24
24
  "hour_suffix": re.compile(r"^(0[0-9]|1[0-9]|2[0-3])[:.][0-5][0-9](?:'te|'de|'da|'den|'dan|'ten|'tan|'deki|'daki)$"),
25
25
  "number_suffix": re.compile(r"^\d+(?:[.,]\d+)*'[a-zA-ZıiİüÜçÇöÖşŞğĞ]+$"),
26
+ "currency_suffix": re.compile(rf"^(?:[{re.escape(''.join(LocalData.currency_symbols()))}]\d{{1,3}}(?:[.,]\d{{3}})*([.,]\d+)?|\d{{1,3}}(?:[.,]\d{{3}})*([.,]\d+)?[{re.escape(''.join(LocalData.currency_symbols()))}])'[a-zA-ZıiİüÜçÇöÖşŞğĞ]+$"),
26
27
  #"hour_12": re.compile(r"^(0[0-9]|1[0-9]|2[0-3])[:.][0-5][0-9]([AP]M)$"),
27
28
  "hour_12": re.compile(r"^(0[1-9]|1[0-2])[:.][0-5][0-9](AM|PM)$"),
28
29
  "percentage_numbers_initial": re.compile(r'^%\d{1,3}(?:[.,]\d+)?$'),
@@ -37,9 +38,9 @@ REGEX_PATTERNS = {
37
38
  "in_parenthesis": re.compile(r'^[(\[{]+[^()\[\]{}]*[)\]}]+}$'),
38
39
  "numbered_title": re.compile(r'^\((\d{1,2})\)|^\[(\d{1,2})\]|^{(\d{1,2})\}'),
39
40
  "in_quotes": re.compile(r'^[\'"][^\'"]*[\'"]$'),
40
- "copyright": re.compile(r'(^©[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9]+$)|(^[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9]+©$)'),
41
- "registered": re.compile(r'(^®[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9]+$)|(^[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9]+®$)'),
42
- "trade_mark": re.compile(r'(^™[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9]+$)|(^[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9]+™$)'),
41
+ "copyright": re.compile(r'(^©[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9_-]+$)|(^[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9_-]+©$)'),
42
+ "registered": re.compile(r'(^®[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9_-]+$)|(^[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9_-]+®$)'),
43
+ "trade_mark": re.compile(r'(^™[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9_-]+$)|(^[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9_-]+™$)'),
43
44
  "bullet_list": re.compile(r'^•[a-zA-ZıiİüÜçÇöÖşŞğĞ0-9]+$'),
44
45
  "three_or_more": re.compile(r'^([{}])\1{{2,}}$'.format(re.escape(string.punctuation))),
45
46
  "roman_number": re.compile(r'^(M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3}))\.?$'),
@@ -187,6 +188,31 @@ class TokenPreProcess:
187
188
  return [("\\", "Punc"), (word[1], "Punc")] + processed_content
188
189
  return None
189
190
 
191
+ @staticmethod
192
+ @apply_charfix
193
+ def is_abbr_with_apostrophe_suffix(word: str) -> list:
194
+ match = re.fullmatch(r"([A-Za-zÇĞİÖŞÜçğıöşü]+\.?)'([A-Za-zÇĞİÖŞÜçğıöşü]+)", word)
195
+ if not match:
196
+ return None
197
+
198
+ abbr_part = match.group(1)
199
+ suffix_part = match.group(2)
200
+ normalized_abbr = CharFix.tr_lowercase(abbr_part)
201
+
202
+ if not abbr_part.endswith("."):
203
+ return None
204
+
205
+ if normalized_abbr not in LocalData.abbrs() and abbr_part not in LocalData.candidate_abbrs():
206
+ return None
207
+
208
+ processed_suffix = TokenProcessor.process_token(suffix_part)
209
+ if isinstance(processed_suffix, tuple):
210
+ processed_suffix = [processed_suffix]
211
+ elif not isinstance(processed_suffix, list):
212
+ processed_suffix = [(suffix_part, "OOV")]
213
+
214
+ return [(abbr_part, "Abbr"), ("'", "Punc")] + processed_suffix
215
+
190
216
  @staticmethod
191
217
  def is_numbered_title(word: str) -> list:
192
218
  # Check if the word matches the "numbered_title" regex pattern
@@ -292,6 +318,19 @@ class TokenPreProcess:
292
318
 
293
319
  return None
294
320
 
321
+ @staticmethod
322
+ @apply_charfix
323
+ def is_currency_suffix(word: str) -> list:
324
+ result = check_regex(word, "currency_suffix")
325
+ if not result:
326
+ return None
327
+
328
+ currency_part, suffix_part = word.rsplit("'", 1)
329
+ if TokenPreProcess.is_currency(currency_part) and suffix_part:
330
+ return [(word, "Currency")]
331
+
332
+ return None
333
+
295
334
  @staticmethod
296
335
  @apply_charfix
297
336
  def is_percentage_numbers(word: str) -> list:
@@ -430,6 +469,27 @@ class TokenPreProcess:
430
469
  result = check_regex(word, "trade_mark")
431
470
  return [(result, "Trademark")] if result else None
432
471
 
472
+ @staticmethod
473
+ @apply_charfix
474
+ def is_marked_with_trailing_punc(word: str) -> list:
475
+ for suffix_len in range(1, len(word)):
476
+ trailing_punc = word[-suffix_len:]
477
+ core = word[:-suffix_len]
478
+
479
+ if not core or not all(char in puncs for char in trailing_punc):
480
+ continue
481
+
482
+ for checker in (
483
+ TokenPreProcess.is_copyright,
484
+ TokenPreProcess.is_registered,
485
+ TokenPreProcess.is_trademark,
486
+ ):
487
+ marked = checker(core)
488
+ if marked:
489
+ return marked + [(char, "Punc") for char in trailing_punc]
490
+
491
+ return None
492
+
433
493
  @staticmethod
434
494
  def is_currency(word: str) -> list:
435
495
  result = check_regex(word, "currency")
@@ -1166,6 +1226,7 @@ regex = [
1166
1226
  TokenPreProcess.is_date,
1167
1227
  TokenPreProcess.is_hour,
1168
1228
  TokenPreProcess.is_hour_suffix,
1229
+ TokenPreProcess.is_currency_suffix,
1169
1230
  TokenPreProcess.is_number_suffix,
1170
1231
  TokenPreProcess.is_number,
1171
1232
  TokenPreProcess.is_mention,
@@ -1173,6 +1234,7 @@ regex = [
1173
1234
  TokenPreProcess.is_in_quotes,
1174
1235
  TokenPreProcess.is_escaped_opening_quote,
1175
1236
  TokenPreProcess.is_opening_quote,
1237
+ TokenPreProcess.is_abbr_with_apostrophe_suffix,
1176
1238
  TokenPreProcess.is_apostrophed,
1177
1239
  TokenPreProcess.is_numbered_title,
1178
1240
  TokenPreProcess.is_parenthesized_with_trailing_colon,
@@ -1181,6 +1243,7 @@ regex = [
1181
1243
  TokenPreProcess.is_registered,
1182
1244
  TokenPreProcess.is_copyright,
1183
1245
  TokenPreProcess.is_trademark,
1246
+ TokenPreProcess.is_marked_with_trailing_punc,
1184
1247
  TokenPreProcess.is_bullet_list,
1185
1248
  TokenPreProcess.is_roman_number,
1186
1249
  TokenPreProcess.is_percentage_numbers_chars,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ts_tokenizer
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: TS Tokenizer is a hybrid (lexicon-based and rule-based) tokenizer designed specifically for tokenizing Turkish texts.
5
5
  Home-page: https://github.com/tanerim/ts_tokenizer
6
6
  Author: Taner Sezer
@@ -3,7 +3,11 @@ MANIFEST.in
3
3
  README.md
4
4
  pyproject.toml
5
5
  setup.py
6
+ tests/test_abbr_apostrophe_suffix.py
7
+ tests/test_abbreviation_lookup.py
8
+ tests/test_currency_suffix.py
6
9
  tests/test_opening_quote_tokenization.py
10
+ tests/test_symbolic_marks.py
7
11
  ts_tokenizer/__init__.py
8
12
  ts_tokenizer/char_fix.py
9
13
  ts_tokenizer/cli.py
File without changes
File without changes
File without changes
File without changes
File without changes