exemplum 1.0.0__py3-none-any.whl
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.
- exemplum-1.0.0.dist-info/METADATA +20 -0
- exemplum-1.0.0.dist-info/RECORD +20 -0
- exemplum-1.0.0.dist-info/WHEEL +5 -0
- exemplum-1.0.0.dist-info/licenses/LICENSE +21 -0
- exemplum-1.0.0.dist-info/top_level.txt +1 -0
- pattern/__init__.py +22 -0
- pattern/checker.py +48 -0
- pattern/judge/__init__.py +8 -0
- pattern/judge/abbreviation.py +68 -0
- pattern/judge/date.py +83 -0
- pattern/judge/number.py +16 -0
- pattern/judge/person.py +44 -0
- pattern/judge/url.py +27 -0
- pattern/machine/__init__.py +8 -0
- pattern/machine/machine.py +114 -0
- pattern/split.py +62 -0
- pattern/text/__init__.py +8 -0
- pattern/text/regex.py +41 -0
- pattern/text/sentence.py +71 -0
- pattern/tok.py +20 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: exemplum
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Author-email: Helmut Konrad Schewe <helmutus@outlook.com>
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/anaticulae/pattern
|
|
7
|
+
Project-URL: Repository, https://github.com/anaticulae/pattern
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: utilo<3.0.0,>=2.109.1
|
|
15
|
+
Provides-Extra: dev
|
|
16
|
+
Requires-Dist: germania==1.32.0; extra == "dev"
|
|
17
|
+
Requires-Dist: utilotest==1.0.4; extra == "dev"
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# pattern
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
exemplum-1.0.0.dist-info/licenses/LICENSE,sha256=9jV_XivjSpyzpEYIFKZGcjDzX8invw3EHEJsGXmGJbA,1077
|
|
2
|
+
pattern/__init__.py,sha256=f45THAWraC_m4_LAWa_cmmyQy53GF9z1mtX-WlzADW8,993
|
|
3
|
+
pattern/checker.py,sha256=syyFSQ6vCBC-2cJFjti-vAZWmjXfj3n5Yoh16e3vu0E,1485
|
|
4
|
+
pattern/split.py,sha256=Eof6M5rcr1y8UVv8qIU2vYI9oJhMN4-Pq8EaPZgrUYs,1922
|
|
5
|
+
pattern/tok.py,sha256=JBXQ9YFXCrB85dIHP17Jdn5NdflIwWgymHJ5bYtkADM,774
|
|
6
|
+
pattern/judge/__init__.py,sha256=XvN2n_gCqUmvquobHOUf2vmlB2hT23ZN8ROBwOJQaOU,557
|
|
7
|
+
pattern/judge/abbreviation.py,sha256=xe3i0Ie8JLg1w0uzgHx4ZIWjMiMXjngUDJkn3fNewhA,1383
|
|
8
|
+
pattern/judge/date.py,sha256=HRlevUxknfT7EVa_ehMSWcu1nivPzI3V0qKAVXfU8v0,1986
|
|
9
|
+
pattern/judge/number.py,sha256=S3kQhny7S_niAwrLR1-DnHR0OHKbz2AbJAHh7qwFL0E,677
|
|
10
|
+
pattern/judge/person.py,sha256=SzLYr4fKOtT7oqVMiJjQuljr_wLhVjEvMXcBVRppduM,1142
|
|
11
|
+
pattern/judge/url.py,sha256=Tpo6YgdHPRf7GUxEpD2_6GgZOQJ3eZanLLA0IGjYb9w,924
|
|
12
|
+
pattern/machine/__init__.py,sha256=iyqCypYQrZOGc2JNXJIjwAzYkzaOzjkd9R5M-5kbFCo,557
|
|
13
|
+
pattern/machine/machine.py,sha256=cX9d0NoRajyBajNLsTabY14OqCL17E0AHeJHcdyJU-o,3345
|
|
14
|
+
pattern/text/__init__.py,sha256=XvN2n_gCqUmvquobHOUf2vmlB2hT23ZN8ROBwOJQaOU,557
|
|
15
|
+
pattern/text/regex.py,sha256=uXuIUjGFBdSyb8U-9y_zVnAbuK1SH4yrc399aUR-oqw,1280
|
|
16
|
+
pattern/text/sentence.py,sha256=L4JXN-nhInumTOu2LSBt6QF6F_hy4uXORH0qUJjDSuM,2118
|
|
17
|
+
exemplum-1.0.0.dist-info/METADATA,sha256=Tz76OY-m4pu9zuCjipHvj6JrUb3Nm3WJYkXP2l74F1w,683
|
|
18
|
+
exemplum-1.0.0.dist-info/WHEEL,sha256=K260EYznzXsJYBQGqmI8VTxEdiZYNvDZwW9cBh9-_MA,91
|
|
19
|
+
exemplum-1.0.0.dist-info/top_level.txt,sha256=Kc-vzR3icWRJAuShud_oaBGtzWTUJ3snCAV4bc677aE,8
|
|
20
|
+
exemplum-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Helmut Konrad Schewe
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pattern
|
pattern/__init__.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#==============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
#------------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2019-2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
#==============================================================================
|
|
9
|
+
|
|
10
|
+
import importlib.metadata
|
|
11
|
+
import os
|
|
12
|
+
|
|
13
|
+
from pattern.machine.machine import Fixed
|
|
14
|
+
from pattern.machine.machine import Method
|
|
15
|
+
from pattern.machine.machine import PatternMixin
|
|
16
|
+
from pattern.machine.machine import Regex
|
|
17
|
+
from pattern.machine.machine import SimpleCleanup
|
|
18
|
+
from pattern.machine.machine import match
|
|
19
|
+
|
|
20
|
+
__version__ = importlib.metadata.version('exemplum')
|
|
21
|
+
|
|
22
|
+
ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
pattern/checker.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import pattern.judge.abbreviation
|
|
11
|
+
import pattern.judge.date
|
|
12
|
+
import pattern.judge.number
|
|
13
|
+
import pattern.judge.person
|
|
14
|
+
import pattern.judge.url
|
|
15
|
+
import pattern.text.sentence
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def is_date(item: str) -> float:
|
|
19
|
+
return pattern.judge.date.validate(item)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def is_url(item: str) -> float:
|
|
23
|
+
return pattern.judge.url.validate(item)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def is_person(item: str) -> float:
|
|
27
|
+
return pattern.judge.person.validate(item)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def is_abbreviation(item: str) -> float:
|
|
31
|
+
return pattern.judge.abbreviation.validate(item)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def is_number(item: str) -> float:
|
|
35
|
+
return pattern.judge.number.validate(item)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def is_samesource(item: str) -> float:
|
|
39
|
+
return pattern.judge.abbreviation.same_source(item)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def is_sentence(item: str) -> float:
|
|
43
|
+
splitted = pattern.text.sentence.split(item)
|
|
44
|
+
if len(splitted) == 1:
|
|
45
|
+
splitted = splitted[0]
|
|
46
|
+
if pattern.text.sentence.is_closed(splitted):
|
|
47
|
+
return 1.0
|
|
48
|
+
return 0.0
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def validate(item: str) -> float:
|
|
12
|
+
item = item.lower()
|
|
13
|
+
result = max((strategy(item) for strategy in (dictionary,)))
|
|
14
|
+
return result
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def dictionary(item):
|
|
18
|
+
if item not in ABBREVIATION:
|
|
19
|
+
return 0.0
|
|
20
|
+
return 1.0
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def same_source(item) -> float:
|
|
24
|
+
if item in SAME_SOURCE:
|
|
25
|
+
return 5.0
|
|
26
|
+
return 0.0
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
ABBREVIATION = {
|
|
30
|
+
'Aufl.',
|
|
31
|
+
'Bd.',
|
|
32
|
+
'Co.',
|
|
33
|
+
'Diss.',
|
|
34
|
+
'Dok.',
|
|
35
|
+
'Forts.',
|
|
36
|
+
'Hrsg.',
|
|
37
|
+
'Jg.',
|
|
38
|
+
'Sp.',
|
|
39
|
+
'Verf.',
|
|
40
|
+
'Verl.',
|
|
41
|
+
'Vol.',
|
|
42
|
+
'a.a.O.',
|
|
43
|
+
'al.',
|
|
44
|
+
'bzw.',
|
|
45
|
+
'ebd.',
|
|
46
|
+
'ebd.:',
|
|
47
|
+
'et al',
|
|
48
|
+
'etc.',
|
|
49
|
+
'ff.'
|
|
50
|
+
'ggf.',
|
|
51
|
+
'lat.',
|
|
52
|
+
'mind.',
|
|
53
|
+
'o.A.',
|
|
54
|
+
'o.J.',
|
|
55
|
+
'o.V.',
|
|
56
|
+
'o.Ä',
|
|
57
|
+
's.',
|
|
58
|
+
'usw.',
|
|
59
|
+
'vgl.',
|
|
60
|
+
'z.B.',
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
ABBREVIATION = {item.lower() for item in ABBREVIATION}
|
|
64
|
+
|
|
65
|
+
SAME_SOURCE = {
|
|
66
|
+
'ebd.',
|
|
67
|
+
'ebd.:',
|
|
68
|
+
}
|
pattern/judge/date.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import utilo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@utilo.cacheme
|
|
14
|
+
def validate(item: str) -> float:
|
|
15
|
+
result = [
|
|
16
|
+
strategy(item) for strategy in (
|
|
17
|
+
day_month_year,
|
|
18
|
+
day_name_year,
|
|
19
|
+
no_date,
|
|
20
|
+
)
|
|
21
|
+
]
|
|
22
|
+
return max(result)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
DATE_FACTOR = 5.0
|
|
26
|
+
|
|
27
|
+
DAY_MONTH_YEAR = utilo.compiles(r"""
|
|
28
|
+
(?P<day>\d{1,2})
|
|
29
|
+
\.
|
|
30
|
+
(?P<month>\d{1,2})
|
|
31
|
+
\.
|
|
32
|
+
(?P<year>(20[012]\d|1[789]\d\d))
|
|
33
|
+
""")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@utilo.cacheme
|
|
37
|
+
def day_month_year(item: str):
|
|
38
|
+
"""\
|
|
39
|
+
>>> day_month_year('25.08.1987')
|
|
40
|
+
5.0
|
|
41
|
+
"""
|
|
42
|
+
matched = DAY_MONTH_YEAR.match(item)
|
|
43
|
+
if not matched:
|
|
44
|
+
return 0.0
|
|
45
|
+
day = int(matched['day'])
|
|
46
|
+
month = int(matched['month'])
|
|
47
|
+
year = int(matched['year'])
|
|
48
|
+
if not 1 <= day <= 31:
|
|
49
|
+
return 0.0
|
|
50
|
+
if not 1 <= month <= 12:
|
|
51
|
+
return 0.0
|
|
52
|
+
if not 1700 <= year <= 2030:
|
|
53
|
+
return 0.0
|
|
54
|
+
return DATE_FACTOR
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
DAY_NAME_YEAR = utilo.compiles(r"""
|
|
58
|
+
(?P<day>\d{1,2})\.[ ]{0,1}
|
|
59
|
+
(?P<month>Januar|Februar|März|April|Mai|Juni|Juli|
|
|
60
|
+
August|September|Oktober|November|Dezember
|
|
61
|
+
)
|
|
62
|
+
[ ]{0,1}
|
|
63
|
+
(?P<year>(20[012]\d|1[789]\d\d))
|
|
64
|
+
""")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@utilo.cacheme
|
|
68
|
+
def day_name_year(item: str) -> float:
|
|
69
|
+
"""\
|
|
70
|
+
>>> day_name_year('20. April 1999')
|
|
71
|
+
5.0
|
|
72
|
+
>>> day_name_year('01. Januar 1733')
|
|
73
|
+
5.0
|
|
74
|
+
"""
|
|
75
|
+
if DAY_NAME_YEAR.match(item):
|
|
76
|
+
return DATE_FACTOR
|
|
77
|
+
return 0.0
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def no_date(item: str):
|
|
81
|
+
if item != 'o.J.':
|
|
82
|
+
return 0.0
|
|
83
|
+
return DATE_FACTOR
|
pattern/judge/number.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def validate(item: str) -> float:
|
|
12
|
+
try:
|
|
13
|
+
int(item)
|
|
14
|
+
except ValueError:
|
|
15
|
+
return 0.0
|
|
16
|
+
return 1.0
|
pattern/judge/person.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def validate(item: str) -> float:
|
|
12
|
+
result = max((strategy(item) for strategy in (dictionary,)))
|
|
13
|
+
return result
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def dictionary(item):
|
|
17
|
+
splitted = item.split(' ')
|
|
18
|
+
for name in splitted:
|
|
19
|
+
if all([
|
|
20
|
+
name not in SURNAME,
|
|
21
|
+
name not in NAME,
|
|
22
|
+
name != 'von',
|
|
23
|
+
]):
|
|
24
|
+
return 0.0
|
|
25
|
+
# prefere person over abbreviation
|
|
26
|
+
return 5.0
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# TODO: LOAD FROM FILE
|
|
30
|
+
|
|
31
|
+
SURNAME = {
|
|
32
|
+
'Angela',
|
|
33
|
+
'Frank',
|
|
34
|
+
'Gero',
|
|
35
|
+
'Martin',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
NAME = {
|
|
39
|
+
'Gatterburg',
|
|
40
|
+
'Hornig',
|
|
41
|
+
'Randow',
|
|
42
|
+
'Simons',
|
|
43
|
+
'o.A.',
|
|
44
|
+
}
|
pattern/judge/url.py
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import urllib.parse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def validate(item: str) -> float:
|
|
14
|
+
result = [strategy(item) for strategy in (urllib_parse,)]
|
|
15
|
+
return max(result)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def urllib_parse(item):
|
|
19
|
+
# TODO: check this
|
|
20
|
+
if '.' not in item:
|
|
21
|
+
return 0.0
|
|
22
|
+
if ',' in item:
|
|
23
|
+
return 0.0
|
|
24
|
+
parsed = urllib.parse.urlparse(item)
|
|
25
|
+
if not parsed:
|
|
26
|
+
return 0.0
|
|
27
|
+
return 1.0
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2021 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
"""\
|
|
10
|
+
Bill Nitzberg und Virginia Lo. Distributed Shared Memory: A Survey
|
|
11
|
+
of Issue and Algorithms. In: Computer 24.8 (Aug. 1991), S. 52-60.
|
|
12
|
+
issn: 0018-9162. doi: 10. 1109/2.84877. url:
|
|
13
|
+
http://dx.doi.org/10.1109/2.84877.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import functools
|
|
17
|
+
import re
|
|
18
|
+
|
|
19
|
+
import utilo
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def match(text: str, patterns: list, improves: list = None) -> dict:
|
|
23
|
+
replaced = text
|
|
24
|
+
# prepare data
|
|
25
|
+
if improves:
|
|
26
|
+
for improve in improves:
|
|
27
|
+
replaced = improve(replaced)
|
|
28
|
+
# collect pattern
|
|
29
|
+
patterns = prepare(patterns)
|
|
30
|
+
collected = {}
|
|
31
|
+
for pattern in patterns:
|
|
32
|
+
matched = pattern(replaced)
|
|
33
|
+
if not matched:
|
|
34
|
+
continue
|
|
35
|
+
before = matched
|
|
36
|
+
if isinstance(matched, str):
|
|
37
|
+
matched = [matched]
|
|
38
|
+
for raw in matched:
|
|
39
|
+
if not isinstance(raw, str):
|
|
40
|
+
raw = raw[1]
|
|
41
|
+
replaced = replaced.replace(raw, '*' * len(raw))
|
|
42
|
+
if pattern.store:
|
|
43
|
+
if pattern.overwrite or pattern.name not in collected:
|
|
44
|
+
collected[pattern.name] = before
|
|
45
|
+
result = {
|
|
46
|
+
"text": text,
|
|
47
|
+
"replaced": replaced,
|
|
48
|
+
"data": collected,
|
|
49
|
+
}
|
|
50
|
+
return result
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class PatternMixin:
|
|
54
|
+
|
|
55
|
+
def __init__(self, name: str):
|
|
56
|
+
self.name = name
|
|
57
|
+
self.store = True
|
|
58
|
+
self.overwrite = False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Fixed(PatternMixin):
|
|
62
|
+
|
|
63
|
+
def __init__(self, const: str):
|
|
64
|
+
super().__init__(name=const.lower())
|
|
65
|
+
self.const = const
|
|
66
|
+
self.store = False
|
|
67
|
+
|
|
68
|
+
def __call__(self, text):
|
|
69
|
+
return re.findall(self.const, text, utilo.NOCASE_VERBOSE)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class Regex(Fixed):
|
|
73
|
+
|
|
74
|
+
def __init__(self, regex: str, name: str):
|
|
75
|
+
super().__init__(const=regex)
|
|
76
|
+
self.name = name.lower()
|
|
77
|
+
self.store = True
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class SimpleCleanup(Fixed):
|
|
81
|
+
|
|
82
|
+
def __init__(self):
|
|
83
|
+
super().__init__('cleanup')
|
|
84
|
+
self.const = r'(\*\s{1,}\*|\(\*{1,}\)|\*\,\s{1,}\*|\*\.\s{1,}\*)'
|
|
85
|
+
self.store = False
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Method(PatternMixin):
|
|
89
|
+
|
|
90
|
+
def __init__(self, method: callable):
|
|
91
|
+
super().__init__(name=method.__name__.lower())
|
|
92
|
+
self.verbose = 'verbose' in utilo.attributes(method)
|
|
93
|
+
if self.verbose:
|
|
94
|
+
method = functools.partial(method, verbose=True)
|
|
95
|
+
self.method = method
|
|
96
|
+
|
|
97
|
+
def __call__(self, text):
|
|
98
|
+
result = self.method(text)
|
|
99
|
+
return result
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def prepare(patterns: list):
|
|
103
|
+
result = []
|
|
104
|
+
for pattern in patterns:
|
|
105
|
+
isclass = str(pattern.__class__) == "<class 'type'>"
|
|
106
|
+
if isinstance(pattern, str):
|
|
107
|
+
result.append(Fixed(const=pattern))
|
|
108
|
+
elif isinstance(pattern, PatternMixin):
|
|
109
|
+
result.append(pattern)
|
|
110
|
+
elif isclass:
|
|
111
|
+
result.append(pattern())
|
|
112
|
+
elif callable(pattern):
|
|
113
|
+
result.append(Method(pattern))
|
|
114
|
+
return result
|
pattern/split.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import pattern.checker
|
|
11
|
+
import pattern.tok
|
|
12
|
+
|
|
13
|
+
STRATEGY = [
|
|
14
|
+
(pattern.tok.Token.ABBREVIATION, pattern.checker.is_abbreviation),
|
|
15
|
+
(pattern.tok.Token.DATE, pattern.checker.is_date),
|
|
16
|
+
(pattern.tok.Token.PAGE, pattern.checker.is_number),
|
|
17
|
+
(pattern.tok.Token.PERSON, pattern.checker.is_person),
|
|
18
|
+
(pattern.tok.Token.SAME_SOURCE, pattern.checker.is_samesource),
|
|
19
|
+
(pattern.tok.Token.URL, pattern.checker.is_url),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def split(line: str):
|
|
24
|
+
comma = ',' in line
|
|
25
|
+
result = []
|
|
26
|
+
|
|
27
|
+
splitted = tokenize(line)
|
|
28
|
+
for token in splitted:
|
|
29
|
+
token = token.strip()
|
|
30
|
+
result.append(analyze(token))
|
|
31
|
+
|
|
32
|
+
if comma:
|
|
33
|
+
items = []
|
|
34
|
+
for item in result:
|
|
35
|
+
items.append(item)
|
|
36
|
+
items.append(pattern.tok.Token.COMMA)
|
|
37
|
+
result = items[:-1] # remove last comma token
|
|
38
|
+
return result
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def tokenize(line: str):
|
|
42
|
+
if ',' in line:
|
|
43
|
+
splitted = line.split(',')
|
|
44
|
+
else:
|
|
45
|
+
splitted = line.split()
|
|
46
|
+
return splitted
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def analyze(token: str) -> pattern.tok.Token:
|
|
50
|
+
result = [strategy(token) for _, strategy in STRATEGY]
|
|
51
|
+
index = max_index(result)
|
|
52
|
+
return STRATEGY[index][0]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def max_index(items) -> int:
|
|
56
|
+
result, value = 0, items[0]
|
|
57
|
+
for index, item in enumerate(items[1:], start=1):
|
|
58
|
+
if item <= value:
|
|
59
|
+
continue
|
|
60
|
+
value = item
|
|
61
|
+
result = index
|
|
62
|
+
return result
|
pattern/text/__init__.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
pattern/text/regex.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def user(
|
|
12
|
+
parameter='text',
|
|
13
|
+
greedy: bool = True,
|
|
14
|
+
newlines: bool = False,
|
|
15
|
+
limit=None,
|
|
16
|
+
):
|
|
17
|
+
if limit is None:
|
|
18
|
+
limit = (1, None)
|
|
19
|
+
ranges = '{%s,%s}' % (limit[0], limit[1] if limit[1] is not None else '')
|
|
20
|
+
greedy = '' if greedy else '?'
|
|
21
|
+
newlines = r'[\n]|' if newlines else ''
|
|
22
|
+
pattern =\
|
|
23
|
+
('('
|
|
24
|
+
f'?P<{parameter}>'
|
|
25
|
+
r'('
|
|
26
|
+
r'[\w\d]|'
|
|
27
|
+
r'[ ]|'
|
|
28
|
+
f'{newlines}'
|
|
29
|
+
r'[=\(\)\[\]{}\<\>]|'
|
|
30
|
+
r'[,;:\.?!]|'
|
|
31
|
+
r'[~`]|'
|
|
32
|
+
r'[@#$%^&*\-_+]|'
|
|
33
|
+
r'[\'\"]|'
|
|
34
|
+
r'[’„“]|'
|
|
35
|
+
r'[–]' # special minus sign
|
|
36
|
+
r')'
|
|
37
|
+
f'{ranges}'
|
|
38
|
+
f'{greedy}'
|
|
39
|
+
r')'
|
|
40
|
+
)
|
|
41
|
+
return pattern
|
pattern/text/sentence.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import contextlib
|
|
11
|
+
|
|
12
|
+
import pattern.checker
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def split(text: str) -> list[str]:
|
|
16
|
+
"""Split a regular `text` into sentence chunks.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
text(str): text to split without any newlines
|
|
20
|
+
Returns:
|
|
21
|
+
list of splitted sentences
|
|
22
|
+
"""
|
|
23
|
+
# TODO: REPLACE WITH EXTERNAL SMART ALTERNATIVE, facebook, google or
|
|
24
|
+
# something else.
|
|
25
|
+
result = []
|
|
26
|
+
current = []
|
|
27
|
+
tokens = text.split(' ')
|
|
28
|
+
for token in tokens:
|
|
29
|
+
if not token:
|
|
30
|
+
continue
|
|
31
|
+
current.append(token)
|
|
32
|
+
token = token.lower() # make approach more robust
|
|
33
|
+
lastchar = token[-1]
|
|
34
|
+
if lastchar == '.':
|
|
35
|
+
if len(token) == 2:
|
|
36
|
+
# W. or G.
|
|
37
|
+
continue
|
|
38
|
+
if pattern.checker.is_abbreviation(token):
|
|
39
|
+
continue
|
|
40
|
+
if token[:-1].isnumeric():
|
|
41
|
+
# 1.; 13.
|
|
42
|
+
continue
|
|
43
|
+
if token.startswith('('):
|
|
44
|
+
# (z.B.)
|
|
45
|
+
continue
|
|
46
|
+
if lastchar in SIGN:
|
|
47
|
+
result.append(' '.join(current))
|
|
48
|
+
current = []
|
|
49
|
+
if current:
|
|
50
|
+
result.append(' '.join(current))
|
|
51
|
+
return result
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def is_closed(token: list) -> bool:
|
|
55
|
+
"""Check that the last character of the last token of a sentences
|
|
56
|
+
contains a sentence close sign."""
|
|
57
|
+
with contextlib.suppress(AttributeError):
|
|
58
|
+
# support str as input
|
|
59
|
+
token = token.split()
|
|
60
|
+
assert token, 'empty sentence'
|
|
61
|
+
last = token[-1].strip()
|
|
62
|
+
last_char = last[-1]
|
|
63
|
+
return last_char in SIGN
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
SIGN = {
|
|
67
|
+
'!',
|
|
68
|
+
'.',
|
|
69
|
+
':',
|
|
70
|
+
'?',
|
|
71
|
+
}
|
pattern/tok.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# C O P Y R I G H T
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Copyright (c) 2020 by Helmut Konrad Fahrendholz. All rights reserved.
|
|
5
|
+
# This file is property of Helmut Konrad Fahrendholz. Any unauthorized copy,
|
|
6
|
+
# use or distribution is an offensive act against international law and may
|
|
7
|
+
# be prosecuted under federal law. Its content is company confidential.
|
|
8
|
+
# =============================================================================
|
|
9
|
+
|
|
10
|
+
import enum
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Token(enum.Enum):
|
|
14
|
+
ABBREVIATION = enum.auto()
|
|
15
|
+
COMMA = enum.auto()
|
|
16
|
+
DATE = enum.auto()
|
|
17
|
+
PAGE = enum.auto()
|
|
18
|
+
PERSON = enum.auto()
|
|
19
|
+
SAME_SOURCE = enum.auto()
|
|
20
|
+
URL = enum.auto()
|