cyg 0.0.dev1__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.
Potentially problematic release.
This version of cyg might be problematic. Click here for more details.
- cyg-0.0.dev1/LICENSE +9 -0
- cyg-0.0.dev1/PKG-INFO +44 -0
- cyg-0.0.dev1/README.md +20 -0
- cyg-0.0.dev1/documentation.txt +199 -0
- cyg-0.0.dev1/pyproject.toml +39 -0
- cyg-0.0.dev1/src/cyg/__init__.py +0 -0
- cyg-0.0.dev1/src/cyg/api.py +178 -0
- cyg-0.0.dev1/src/cyg/cygnet.py +47 -0
- cyg-0.0.dev1/src/cyg/data/help.txt +4 -0
- cyg-0.0.dev1/src/cyg/db.py +43 -0
- cyg-0.0.dev1/src/cyg/queries.py +284 -0
- cyg-0.0.dev1/src/cyg/subclasses.py +200 -0
cyg-0.0.dev1/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 CultureLab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the " Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
cyg-0.0.dev1/PKG-INFO
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: cyg
|
|
3
|
+
Version: 0.0.dev1
|
|
4
|
+
Summary: A package to query Cygnet, a reformulation of the Open Multilingual Wordnet
|
|
5
|
+
Project-URL: Homepage, https://github.com/smpouli/cygnet_python_package
|
|
6
|
+
Project-URL: Documentation, https://github.com/smpouli/cygnet_python_package/blob/main/documentation.txt
|
|
7
|
+
Project-URL: Repository, https://github.com/smpouli/cygnet_python_package
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: Wordnet,language,linguistics,multilingual
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Information Technology
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Topic :: Database
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
20
|
+
Classifier: Topic :: Text Processing
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Requires-Dist: urllib3
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# Product Name
|
|
26
|
+
>Cyg is a Python library conceived to query Cygnet, a reformulation of the Open Multilingual WordNet.
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
Cyg makes it possible to return ilis of concepts in different languages and also to compare senses, definitions and relationships between concepts. The database can also be queried online: https://cygnet.maudslay.eu/.
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## Release History
|
|
34
|
+
0.0.1b1
|
|
35
|
+
* Work in progress
|
|
36
|
+
|
|
37
|
+
## Meta
|
|
38
|
+
|
|
39
|
+
Distributed under the MIT license. See ``LICENSE`` for more information.
|
|
40
|
+
|
|
41
|
+
[https://github.com/smpouli/cygnet_python_package]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
cyg-0.0.dev1/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Product Name
|
|
2
|
+
>Cyg is a Python library conceived to query Cygnet, a reformulation of the Open Multilingual WordNet.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
Cyg makes it possible to return ilis of concepts in different languages and also to compare senses, definitions and relationships between concepts. The database can also be queried online: https://cygnet.maudslay.eu/.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Release History
|
|
10
|
+
0.0.1b1
|
|
11
|
+
* Work in progress
|
|
12
|
+
|
|
13
|
+
## Meta
|
|
14
|
+
|
|
15
|
+
Distributed under the MIT license. See ``LICENSE`` for more information.
|
|
16
|
+
|
|
17
|
+
[https://github.com/smpouli/cygnet_python_package]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
|
|
2
|
+
First step:
|
|
3
|
+
|
|
4
|
+
import cygnet
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Use cases
|
|
8
|
+
|
|
9
|
+
1/ Count all concepts
|
|
10
|
+
|
|
11
|
+
c = cygnet.Cygnet().concepts()
|
|
12
|
+
print (len(c))
|
|
13
|
+
|
|
14
|
+
* Filter by POS only
|
|
15
|
+
|
|
16
|
+
c = cygnet.Cygnet().concepts(pos="noun")
|
|
17
|
+
|
|
18
|
+
Note: only four POS currently present (noun, verb, adj and adv) in the table used
|
|
19
|
+
|
|
20
|
+
* Filter by language(s)
|
|
21
|
+
|
|
22
|
+
c = cygnet.Cygnet().concepts(langs="it")
|
|
23
|
+
|
|
24
|
+
c = cygnet.Cygnet().concepts(pos="adv", langs="it")
|
|
25
|
+
|
|
26
|
+
* Filter by by form
|
|
27
|
+
|
|
28
|
+
c = cygnet.Cygnet().concepts(form="bal")
|
|
29
|
+
|
|
30
|
+
c = cygnet.Cygnet().concepts(form="bal", pos="noun", langs="fr")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
2/ Working with concepts
|
|
36
|
+
|
|
37
|
+
=> find the POS and index of a concept
|
|
38
|
+
for a in c:
|
|
39
|
+
print (a.pos())
|
|
40
|
+
|
|
41
|
+
=> find the index of a concept
|
|
42
|
+
for a in c:
|
|
43
|
+
print (a.index())
|
|
44
|
+
|
|
45
|
+
=> find the definition of a concept
|
|
46
|
+
# the offset is not implemented because the data is lacking
|
|
47
|
+
for a in c:
|
|
48
|
+
f = a.definition("es")
|
|
49
|
+
print (f.text())
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
=> find semantically related concepts:
|
|
53
|
+
|
|
54
|
+
c =cygnet.Cygnet().concepts(form="cheek", langs="en")
|
|
55
|
+
for a in c:
|
|
56
|
+
rel=a.holonyms()
|
|
57
|
+
|
|
58
|
+
Available relationships:
|
|
59
|
+
- hypernymy: a.hypernyms()
|
|
60
|
+
- hyponyny: a.hyponyms()
|
|
61
|
+
- meronymy: a.meronyms ()
|
|
62
|
+
- holonyms: a.holonyms()
|
|
63
|
+
|
|
64
|
+
=> Retrieve senses from concepts:
|
|
65
|
+
|
|
66
|
+
c =cygnet.Cygnet().concepts(form="cheek", langs="en")
|
|
67
|
+
for a in c:
|
|
68
|
+
senses=a.senses("en")
|
|
69
|
+
print (a, senses)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
=> Retrieve lexemes from concepts:
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
c =cygnet.Cygnet().concepts(form="cheek", langs="en")
|
|
76
|
+
for a in c:
|
|
77
|
+
words=a.lexemes("en")
|
|
78
|
+
print (a, words)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
3/ Count all lexemes
|
|
82
|
+
|
|
83
|
+
c = cygnet.Cygnet().lexemes()
|
|
84
|
+
print (len(c))
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
* Filter by form
|
|
88
|
+
|
|
89
|
+
c = cygnet.Cygnet().lexemes(form="but")
|
|
90
|
+
print (c)
|
|
91
|
+
|
|
92
|
+
* Filter from language(s)
|
|
93
|
+
|
|
94
|
+
c = cygnet.Cygnet().lexemes(form="but", langs=["en", "fr"])
|
|
95
|
+
|
|
96
|
+
print (c)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
4/ Working with lexemes
|
|
101
|
+
|
|
102
|
+
=> find the index of the lexeme
|
|
103
|
+
|
|
104
|
+
c =cygnet.Cygnet().concepts(form="cheek", langs="en")
|
|
105
|
+
for a in c:
|
|
106
|
+
words=a.lexemes()
|
|
107
|
+
for w in words:
|
|
108
|
+
print (w.index())
|
|
109
|
+
|
|
110
|
+
=> find the language of the lexeme:
|
|
111
|
+
c =cygnet.Cygnet().concepts(form="sudden", langs="en")
|
|
112
|
+
print (c)
|
|
113
|
+
for a in c:
|
|
114
|
+
words=a.lexemes()
|
|
115
|
+
for w in words:
|
|
116
|
+
print (w.lang())
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
=> find the lemma
|
|
120
|
+
c =cygnet.Cygnet().concepts(form="been")
|
|
121
|
+
for a in c:
|
|
122
|
+
words=a.lexemes("en")
|
|
123
|
+
for w in words:
|
|
124
|
+
print (w.lemma())
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
=> print all forms of the lemma:
|
|
128
|
+
c =cygnet.Cygnet().concepts(form="been")
|
|
129
|
+
for a in c:
|
|
130
|
+
words=a.lexemes("en")
|
|
131
|
+
for w in words:
|
|
132
|
+
print (w.all_forms())
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
=> find the concepts related to the lexeme
|
|
136
|
+
|
|
137
|
+
c =cygnet.Cygnet().concepts(form="pray")
|
|
138
|
+
for a in c:
|
|
139
|
+
words=a.lexemes("en")
|
|
140
|
+
for w in words:
|
|
141
|
+
print (w.concepts())
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
=> find the senses related to the lexeme
|
|
145
|
+
c =cygnet.Cygnet().concepts(form="pray")
|
|
146
|
+
for a in c:
|
|
147
|
+
words=a.lexemes("en")
|
|
148
|
+
for w in words:
|
|
149
|
+
print (w.senses())
|
|
150
|
+
|
|
151
|
+
5/ Count all senses
|
|
152
|
+
|
|
153
|
+
c = cygnet.Cygnet().senses()
|
|
154
|
+
print (len(c))
|
|
155
|
+
|
|
156
|
+
* Filter by form
|
|
157
|
+
|
|
158
|
+
c = cygnet.Cygnet().senses(form="chaos")
|
|
159
|
+
print (c)
|
|
160
|
+
|
|
161
|
+
* Filter from language(s)
|
|
162
|
+
|
|
163
|
+
c = cygnet.Cygnet().senses(form="chaos", langs=["en", "fr"])
|
|
164
|
+
print (c)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
6/ Working with senses
|
|
168
|
+
|
|
169
|
+
=> find the index of the sense
|
|
170
|
+
|
|
171
|
+
c = cygnet.Cygnet().senses(form="chaos", langs=["en", "fr"])
|
|
172
|
+
|
|
173
|
+
for b in c:
|
|
174
|
+
print (b, b.index())
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
=> find the concepts related to the sense
|
|
179
|
+
c = cygnet.Cygnet().senses(form="chaos", langs=["en"])
|
|
180
|
+
|
|
181
|
+
for b in c:
|
|
182
|
+
print (b, b.concept())
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
=> find the lexeme related to the sense:
|
|
186
|
+
|
|
187
|
+
c = cygnet.Cygnet().senses(form="chaos")
|
|
188
|
+
|
|
189
|
+
for b in c:
|
|
190
|
+
print (b, b.lexeme(), b.lang())
|
|
191
|
+
|
|
192
|
+
=> display examples of the sense and offsets
|
|
193
|
+
|
|
194
|
+
c =cygnet.Cygnet().concepts(form="sordid")
|
|
195
|
+
for a in c:
|
|
196
|
+
words=a.lexemes("en")
|
|
197
|
+
for w in words:
|
|
198
|
+
for d in w.senses():
|
|
199
|
+
print (d, d.examples().text(), d.examples().sense_offsets())
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[tool.hatch.build.targets.wheel]
|
|
6
|
+
packages = ["src/cyg"]
|
|
7
|
+
sources = ["src/cyg"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
[project]
|
|
11
|
+
name = "cyg"
|
|
12
|
+
version = "0.0.dev1"
|
|
13
|
+
description = "A package to query Cygnet, a reformulation of the Open Multilingual Wordnet"
|
|
14
|
+
keywords = ["Wordnet", "multilingual", "linguistics", "language"]
|
|
15
|
+
readme = "README.md"
|
|
16
|
+
requires-python = ">=3.9"
|
|
17
|
+
dependencies = [
|
|
18
|
+
"urllib3",
|
|
19
|
+
]
|
|
20
|
+
classifiers = [
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Development Status :: 4 - Beta",
|
|
24
|
+
"Intended Audience :: Developers",
|
|
25
|
+
"Intended Audience :: Information Technology",
|
|
26
|
+
"Intended Audience :: Science/Research",
|
|
27
|
+
"License :: OSI Approved :: MIT License",
|
|
28
|
+
"Topic :: Text Processing",
|
|
29
|
+
"Topic :: Database",
|
|
30
|
+
"Topic :: Scientific/Engineering :: Information Analysis"
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
license = "MIT"
|
|
34
|
+
license-files = ["LICEN[CS]E*"]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/smpouli/cygnet_python_package"
|
|
38
|
+
Documentation = "https://github.com/smpouli/cygnet_python_package/blob/main/documentation.txt"
|
|
39
|
+
Repository = "https://github.com/smpouli/cygnet_python_package"
|
|
File without changes
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from typing import List, Tuple, Literal, Optional
|
|
4
|
+
|
|
5
|
+
POS = Literal["noun", "verb", "adj", "adv", "adp", "unk", "conj", "nref"]
|
|
6
|
+
|
|
7
|
+
class Cygnet(ABC):
|
|
8
|
+
"""Top-level access point for querying the Cygnet database."""
|
|
9
|
+
|
|
10
|
+
@abstractmethod
|
|
11
|
+
def concepts(self,
|
|
12
|
+
form: Optional[str] = None,
|
|
13
|
+
langs: List[str] | str | None = None,
|
|
14
|
+
pos : Optional[POS] = None
|
|
15
|
+
) -> List[AbstractConcept]:
|
|
16
|
+
"""Returns all concepts, optionally filtered by wordform, language(s), and/or part of speech."""
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def concept(self,
|
|
21
|
+
ili: str
|
|
22
|
+
) -> Optional[AbstractConcept]:
|
|
23
|
+
"""Returns the concept identified by the given ILI (Interlingual Index) string, or None if not found."""
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def senses(self,
|
|
28
|
+
form: Optional[str] = None,
|
|
29
|
+
langs: List[str] | str | None = None
|
|
30
|
+
) -> List[AbstractSense]:
|
|
31
|
+
"""Returns all senses, optionally filtered by wordform and/or language(s)."""
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@abstractmethod
|
|
35
|
+
def lexemes(self,
|
|
36
|
+
form: Optional[str] = None,
|
|
37
|
+
langs: List[str] | str | None = None
|
|
38
|
+
) -> List[AbstractLexeme]:
|
|
39
|
+
"""Returns all lexemes, optionally filtered by wordform and/or language(s)."""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
@abstractmethod
|
|
43
|
+
def langs(self) -> List[str]:
|
|
44
|
+
"""Returns the list of language codes available in the database."""
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
class AbstractConcept(ABC):
|
|
48
|
+
"""A language-independent concept, corresponding to a synset in traditional Wordnet releases."""
|
|
49
|
+
|
|
50
|
+
@abstractmethod
|
|
51
|
+
def definition(self,
|
|
52
|
+
lang: str = "en"
|
|
53
|
+
) -> Optional[AbstractAnnotatedString]:
|
|
54
|
+
"""Returns the definition of this concept in the given language, or None if unavailable."""
|
|
55
|
+
pass
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def pos(self) -> POS:
|
|
59
|
+
"""Returns the part of speech (ontological category) of this concept."""
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
@abstractmethod
|
|
63
|
+
def index(self) -> str:
|
|
64
|
+
"""Returns the unique identifier (ILI) for this concept."""
|
|
65
|
+
pass
|
|
66
|
+
|
|
67
|
+
@abstractmethod
|
|
68
|
+
def senses(self,
|
|
69
|
+
lang: Optional[str] = None
|
|
70
|
+
) -> List[AbstractSense]:
|
|
71
|
+
"""Returns all senses linked to this concept, optionally filtered by language."""
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
@abstractmethod
|
|
75
|
+
def lexemes(self,
|
|
76
|
+
lang: Optional[str] = None
|
|
77
|
+
) -> List[AbstractLexeme]:
|
|
78
|
+
"""Returns all lexemes linked to senses of this concept, optionally filtered by language."""
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
@abstractmethod
|
|
82
|
+
def hypernyms(self) -> List[AbstractConcept]:
|
|
83
|
+
"""Returns concepts that are connected to this concept by a hypernym relation."""
|
|
84
|
+
pass
|
|
85
|
+
|
|
86
|
+
@abstractmethod
|
|
87
|
+
def hyponyms(self) -> List[AbstractConcept]:
|
|
88
|
+
"""Returns concepts that are connected to this concept by a hyponymy relation."""
|
|
89
|
+
pass
|
|
90
|
+
|
|
91
|
+
@abstractmethod
|
|
92
|
+
def meronyms(self) -> List[AbstractConcept]:
|
|
93
|
+
"""Returns concepts that are connected to this concept by a meronymy relation."""
|
|
94
|
+
pass
|
|
95
|
+
|
|
96
|
+
@abstractmethod
|
|
97
|
+
def holonyms(self) -> List[AbstractConcept]:
|
|
98
|
+
"""Returns concepts that are connected to this concept by a holonymy relation."""
|
|
99
|
+
pass
|
|
100
|
+
|
|
101
|
+
class AbstractSense(ABC):
|
|
102
|
+
"""A pairing of a lexeme with a concept, representing one meaning of a word."""
|
|
103
|
+
|
|
104
|
+
@abstractmethod
|
|
105
|
+
def index(self) -> str:
|
|
106
|
+
"""Returns the unique identifier for this sense."""
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
@abstractmethod
|
|
110
|
+
def examples(self) -> List[AbstractAnnotatedString]:
|
|
111
|
+
"""Returns usage examples illustrating this sense."""
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def concept(self) -> AbstractConcept:
|
|
116
|
+
"""Returns the concept associated with this sense (the signified)."""
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
@abstractmethod
|
|
120
|
+
def lexeme(self) -> AbstractLexeme:
|
|
121
|
+
"""Returns the lexeme associated with this sense (the signifier)."""
|
|
122
|
+
pass
|
|
123
|
+
|
|
124
|
+
@abstractmethod
|
|
125
|
+
def lang(self) -> str:
|
|
126
|
+
"""Returns the language code of this sense's lexeme."""
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
class AbstractLexeme(ABC):
|
|
130
|
+
"""A wordform in a specific language, with all possible inflections."""
|
|
131
|
+
|
|
132
|
+
@abstractmethod
|
|
133
|
+
def index(self) -> str:
|
|
134
|
+
"""Returns the unique identifier for this lexeme."""
|
|
135
|
+
pass
|
|
136
|
+
|
|
137
|
+
@abstractmethod
|
|
138
|
+
def lang(self) -> str:
|
|
139
|
+
"""Returns the language code of this lexeme."""
|
|
140
|
+
pass
|
|
141
|
+
|
|
142
|
+
@abstractmethod
|
|
143
|
+
def lemma(self) -> str:
|
|
144
|
+
"""Returns the canonical form of this lexeme."""
|
|
145
|
+
pass
|
|
146
|
+
|
|
147
|
+
@abstractmethod
|
|
148
|
+
def all_forms(self) -> List[str]:
|
|
149
|
+
"""Returns all inflected forms of this lexeme (including the lemma)."""
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
@abstractmethod
|
|
153
|
+
def senses(self) -> List[AbstractSense]:
|
|
154
|
+
"""Returns every sense that references this lexeme."""
|
|
155
|
+
pass
|
|
156
|
+
|
|
157
|
+
@abstractmethod
|
|
158
|
+
def concepts(self) -> List[AbstractConcept]:
|
|
159
|
+
"""Returns every concept linked to this lexeme via a sense."""
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
class AbstractAnnotatedString(ABC):
|
|
163
|
+
"""A string of text with sense annotations."""
|
|
164
|
+
|
|
165
|
+
@abstractmethod
|
|
166
|
+
def text(self) -> str:
|
|
167
|
+
"""Return the plain text content of this string."""
|
|
168
|
+
pass
|
|
169
|
+
|
|
170
|
+
@abstractmethod
|
|
171
|
+
def lang(self) -> str:
|
|
172
|
+
"""Return the language code of the language this string is in."""
|
|
173
|
+
pass
|
|
174
|
+
|
|
175
|
+
@abstractmethod
|
|
176
|
+
def sense_offsets(self) -> List[Tuple[AbstractSense, int, int]]:
|
|
177
|
+
"""Return a list of (sense, start, end) tuples marking annotated spans within the text."""
|
|
178
|
+
pass
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import List, Optional
|
|
2
|
+
import queries
|
|
3
|
+
from api import AbstractConcept, AbstractSense, AbstractLexeme, POS
|
|
4
|
+
from subclasses import*
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Cygnet:
|
|
8
|
+
"""
|
|
9
|
+
main class of the module
|
|
10
|
+
"""
|
|
11
|
+
def __init__(self):
|
|
12
|
+
pass
|
|
13
|
+
|
|
14
|
+
def concepts(self,
|
|
15
|
+
form: Optional[str] = None,
|
|
16
|
+
langs=None,
|
|
17
|
+
pos: Optional[POS] = None
|
|
18
|
+
) -> List[AbstractConcept]:
|
|
19
|
+
rows = queries.fetch_concepts(form=form, langs=langs, pos=pos)
|
|
20
|
+
return [Concept(row) for row in rows]
|
|
21
|
+
|
|
22
|
+
def concept(self, ili: str) -> Optional[AbstractConcept]:
|
|
23
|
+
row = queries.fetch_concept_by_ili(ili)
|
|
24
|
+
if row is None:
|
|
25
|
+
return None
|
|
26
|
+
else:
|
|
27
|
+
return Concept(row)
|
|
28
|
+
|
|
29
|
+
def senses(self,
|
|
30
|
+
form: Optional[str] = None,
|
|
31
|
+
langs=None
|
|
32
|
+
) -> List[AbstractSense]:
|
|
33
|
+
rows = queries.fetch_senses(form=form, langs=langs)
|
|
34
|
+
return [Sense(row) for row in rows]
|
|
35
|
+
|
|
36
|
+
def lexemes(self,
|
|
37
|
+
form: Optional[str] = None,
|
|
38
|
+
langs=None
|
|
39
|
+
) -> List[AbstractLexeme]:
|
|
40
|
+
rows = queries.fetch_lexemes(form=form, langs=langs)
|
|
41
|
+
return [Lexeme(row) for row in rows]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def langs(self) -> List[str]:
|
|
45
|
+
languages = queries.print_all_languages()
|
|
46
|
+
return [l[0] for l in languages]
|
|
47
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import urllib.request
|
|
4
|
+
import os, gzip, shutil
|
|
5
|
+
import sqlite3
|
|
6
|
+
|
|
7
|
+
# database checking and downloading
|
|
8
|
+
path_to_installed_database=Path('src/cyg/data/cygnet.db')
|
|
9
|
+
|
|
10
|
+
if path_to_installed_database.exists():
|
|
11
|
+
# connexion to the database
|
|
12
|
+
conn = sqlite3.connect('src/cyg/data/cygnet.db')
|
|
13
|
+
Database = conn.cursor()
|
|
14
|
+
else:
|
|
15
|
+
download_url = "https://github.com/rowanhm/cygnet/releases/latest/download/cygnet.db.gz"
|
|
16
|
+
|
|
17
|
+
gz_file = Path("src/cyg/data/cygnet.db.gz")
|
|
18
|
+
output_file = Path("src/cyg/data/cygnet.db")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
try:
|
|
22
|
+
# Download
|
|
23
|
+
print ("The Cygnet database needs to be downloaded. This will happen only once.")
|
|
24
|
+
print ("Downloading Cygnet database...")
|
|
25
|
+
urllib.request.urlretrieve(download_url, gz_file)
|
|
26
|
+
print ("Cygnet database successfully downloaded.")
|
|
27
|
+
# Decompress
|
|
28
|
+
with gzip.open(gz_file, "rb") as gz:
|
|
29
|
+
with open(output_file, "wb") as output:
|
|
30
|
+
shutil.copyfileobj(gz, output)
|
|
31
|
+
|
|
32
|
+
os.remove(gz_file)
|
|
33
|
+
print("Cygnet database successfully extracted and stored.")
|
|
34
|
+
|
|
35
|
+
# connexion to the database
|
|
36
|
+
conn = sqlite3.connect('src/cyg/data/cygnet.db')
|
|
37
|
+
Database = conn.cursor()
|
|
38
|
+
except:
|
|
39
|
+
print ("An error occurred, please try again or look at the help file in the data folder.")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
from db import Database
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#-------- queries related to cygnet.py
|
|
6
|
+
|
|
7
|
+
def fetch_concepts(form: Optional[str] = None,
|
|
8
|
+
langs=None,
|
|
9
|
+
pos: Optional[str] = None):
|
|
10
|
+
"""
|
|
11
|
+
Retrieve all concepts optionally filtered by form, languages and/or POS
|
|
12
|
+
"""
|
|
13
|
+
sql_concept = """SELECT DISTINCT synsets.rowid, LOWER(synsets.pos), ili FROM synsets
|
|
14
|
+
JOIN senses ON synsets.rowid = senses.synset_rowid
|
|
15
|
+
JOIN entries ON entries.rowid = senses.entry_rowid
|
|
16
|
+
JOIN forms ON entries.rowid = forms.entry_rowid
|
|
17
|
+
JOIN languages ON languages.rowid = entries.language_rowid"""
|
|
18
|
+
params: list = []
|
|
19
|
+
conditions = []
|
|
20
|
+
if form:
|
|
21
|
+
conditions.append(" form=?")
|
|
22
|
+
params += [form]
|
|
23
|
+
if langs:
|
|
24
|
+
lang_list = [langs] if isinstance(langs, str) else langs
|
|
25
|
+
placeholders = ",".join("?" * len(lang_list))
|
|
26
|
+
conditions.append(f" languages.code IN ({placeholders})")
|
|
27
|
+
params += lang_list
|
|
28
|
+
if pos:
|
|
29
|
+
conditions.append(" LOWER(synsets.pos)=?")
|
|
30
|
+
params.append(pos)
|
|
31
|
+
|
|
32
|
+
if len(conditions)==1:
|
|
33
|
+
sql_concept= sql_concept + "\n WHERE " + conditions[0] + "\n ORDER BY synsets.rowid ASC"
|
|
34
|
+
|
|
35
|
+
elif len(conditions)>1:
|
|
36
|
+
condition = "\n WHERE " + " AND ".join(conditions)
|
|
37
|
+
sql_concept +=f""" {condition}
|
|
38
|
+
ORDER BY synsets.rowid ASC"""
|
|
39
|
+
|
|
40
|
+
return Database.execute(sql_concept, tuple(params)).fetchall()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def fetch_concept_by_ili ( ili: str):
|
|
47
|
+
"""
|
|
48
|
+
Retrieve the specific concept related to an ILI
|
|
49
|
+
"""
|
|
50
|
+
return Database.execute(
|
|
51
|
+
"""SELECT rowid, LOWER(pos), ili FROM synsets
|
|
52
|
+
WHERE ili=?""", (ili,)
|
|
53
|
+
).fetchone()
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def fetch_senses(form: Optional[str] = None, langs=None):
|
|
57
|
+
"""
|
|
58
|
+
Retrieve all concepts optionnally filtered by form and/or languages
|
|
59
|
+
"""
|
|
60
|
+
sql_sense= "SELECT DISTINCT senses.rowid, senses.synset_rowid, senses.entry_rowid FROM senses"
|
|
61
|
+
params: list = []
|
|
62
|
+
conditions = []
|
|
63
|
+
if form:
|
|
64
|
+
conditions.append(" form=?")
|
|
65
|
+
params += [form]
|
|
66
|
+
if langs:
|
|
67
|
+
lang_list = [langs] if isinstance(langs, str) else langs
|
|
68
|
+
placeholders = ",".join("?" * len(lang_list))
|
|
69
|
+
conditions.append(f" languages.code IN ({placeholders})")
|
|
70
|
+
params += lang_list
|
|
71
|
+
|
|
72
|
+
if len(conditions)==1:
|
|
73
|
+
sql_sense += """ \n JOIN entries ON entries.rowid = senses.entry_rowid
|
|
74
|
+
JOIN forms ON entries.rowid = forms.entry_rowid
|
|
75
|
+
JOIN languages ON languages.rowid = entries.language_rowid""" + "\n WHERE " + conditions[0] + """\n ORDER BY senses.sense_index, senses.rowid"""
|
|
76
|
+
|
|
77
|
+
elif len(conditions)>1:
|
|
78
|
+
condition = "\n WHERE " + " AND ".join(conditions)
|
|
79
|
+
sql_sense +=f""" \n JOIN entries ON entries.rowid = senses.entry_rowid
|
|
80
|
+
JOIN forms ON entries.rowid = forms.entry_rowid
|
|
81
|
+
JOIN languages ON languages.rowid = entries.language_rowid
|
|
82
|
+
{condition}
|
|
83
|
+
ORDER BY senses.sense_index, senses.rowid"""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
return Database.execute(sql_sense, tuple(params)).fetchall()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def fetch_lexemes(form: Optional[str] = None, langs=None):
|
|
92
|
+
"""
|
|
93
|
+
Retrieve all lexemes optionnally filtered by form and/or languages
|
|
94
|
+
"""
|
|
95
|
+
sql_lexeme= "SELECT DISTINCT entries.rowid from entries"
|
|
96
|
+
params: list = []
|
|
97
|
+
conditions = []
|
|
98
|
+
if form:
|
|
99
|
+
conditions.append(" form=?")
|
|
100
|
+
params += [form]
|
|
101
|
+
if langs:
|
|
102
|
+
lang_list = [langs] if isinstance(langs, str) else langs
|
|
103
|
+
placeholders = ",".join("?" * len(lang_list))
|
|
104
|
+
conditions.append(f" languages.code IN ({placeholders})")
|
|
105
|
+
params += lang_list
|
|
106
|
+
|
|
107
|
+
if len(conditions)==1:
|
|
108
|
+
sql_lexeme += """ \n JOIN senses ON entries.rowid = senses.entry_rowid
|
|
109
|
+
JOIN forms ON entries.rowid = forms.entry_rowid
|
|
110
|
+
JOIN languages ON languages.rowid = entries.language_rowid""" + "\n WHERE " + conditions[0] + """\n ORDER BY entries.rowid ASC"""
|
|
111
|
+
|
|
112
|
+
elif len(conditions)>1:
|
|
113
|
+
condition = "\n WHERE " + " AND ".join(conditions)
|
|
114
|
+
sql_lexeme +=f""" \n JOIN forms ON entries.rowid = forms.entry_rowid
|
|
115
|
+
JOIN languages ON languages.rowid = entries.language_rowid
|
|
116
|
+
{condition}
|
|
117
|
+
ORDER BY entries.rowid ASC"""
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
return Database.execute(sql_lexeme, tuple(params)).fetchall()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def print_all_languages ():
|
|
124
|
+
"""
|
|
125
|
+
Display the codes of all languages available in the database
|
|
126
|
+
"""
|
|
127
|
+
return Database.execute("""SELECT code FROM languages ORDER BY code""" ).fetchall()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
#-------- queries related to the class concept
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def fetch_definition(rowid, lang: str):
|
|
134
|
+
"""
|
|
135
|
+
Retrieve the definition of a concept in a given language
|
|
136
|
+
"""
|
|
137
|
+
sql_def = """SELECT definitions.definition, languages.code FROM definitions
|
|
138
|
+
JOIN languages ON languages.rowid=definitions.language_rowid
|
|
139
|
+
WHERE definitions.synset_rowid=? AND languages.code=?"""
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
return Database.execute(sql_def, (rowid, lang)).fetchone()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def fetch_senses_by_concept(rowid,lang: Optional[str] = None):
|
|
146
|
+
"""
|
|
147
|
+
Retrieve the senses of a concept optionally filtered by language
|
|
148
|
+
"""
|
|
149
|
+
sql_senses_concept=""" SELECT DISTINCT senses.rowid, senses.synset_rowid, senses.entry_rowid FROM senses"""
|
|
150
|
+
params=[rowid]
|
|
151
|
+
|
|
152
|
+
if lang:
|
|
153
|
+
sql_senses_concept += """\n JOIN entries ON entries.rowid=senses.entry_rowid
|
|
154
|
+
JOIN languages on entries.language_rowid=languages.rowid
|
|
155
|
+
WHERE synset_rowid = ? AND languages.code=?
|
|
156
|
+
ORDER BY senses.sense_index, senses.rowid"""
|
|
157
|
+
params.append(lang)
|
|
158
|
+
else:
|
|
159
|
+
sql_senses_concept += """ \n WHERE synset_rowid = ?
|
|
160
|
+
ORDER BY senses.sense_index, senses.rowid"""
|
|
161
|
+
|
|
162
|
+
return Database.execute(sql_senses_concept, tuple(params)).fetchall()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def fetch_lexemes_by_concept(rowid,lang: Optional[str] = None):
|
|
168
|
+
"""
|
|
169
|
+
Retrieve the lexemes related to a concept optionally filtered by language
|
|
170
|
+
"""
|
|
171
|
+
sql_lexemes_concept=""" SELECT DISTINCT senses.entry_rowid FROM senses"""
|
|
172
|
+
params=[rowid]
|
|
173
|
+
|
|
174
|
+
if lang:
|
|
175
|
+
sql_lexemes_concept += """\n JOIN entries ON entries.rowid=senses.entry_rowid
|
|
176
|
+
JOIN languages on entries.language_rowid=languages.rowid
|
|
177
|
+
WHERE senses.synset_rowid = ? AND languages.code=?
|
|
178
|
+
ORDER BY senses.entry_rowid ASC"""
|
|
179
|
+
params.append(lang)
|
|
180
|
+
else:
|
|
181
|
+
sql_lexemes_concept += """ \n WHERE senses.synset_rowid = ?
|
|
182
|
+
ORDER BY senses.entry_rowid ASC"""
|
|
183
|
+
|
|
184
|
+
return Database.execute(sql_lexemes_concept, tuple(params)).fetchall()
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def fetch_related_synsets(rowid,relation):
|
|
190
|
+
"""
|
|
191
|
+
Retrieve the hyperonyms, hyponyms, meronyms or holonyms of a concept
|
|
192
|
+
"""
|
|
193
|
+
sql_rel="""SELECT target_rowid, LOWER(synsets.pos), synsets.ili FROM synset_relations
|
|
194
|
+
JOIN synsets ON target_rowid=synsets.rowid
|
|
195
|
+
WHERE source_rowid=? AND type_rowid=?
|
|
196
|
+
ORDER BY target_rowid ASC"""
|
|
197
|
+
|
|
198
|
+
return Database.execute(sql_rel, (rowid,relation)).fetchall()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
#-------- queries related to the class Sense
|
|
204
|
+
|
|
205
|
+
def fetch_examples(sense_rowid):
|
|
206
|
+
"""
|
|
207
|
+
Retrieve all examples of a particular sense
|
|
208
|
+
"""
|
|
209
|
+
sql_examples = """ SELECT example, languages.code, example_annotations.sense_rowid, senses.synset_rowid, senses.entry_rowid, example_annotations.start_offset, example_annotations.end_offset FROM examples
|
|
210
|
+
JOIN sense_examples ON examples.rowid= sense_examples.example_rowid
|
|
211
|
+
JOIN example_annotations ON example_annotations.rowid=examples.rowid
|
|
212
|
+
JOIN senses ON senses.rowid=sense_examples.sense_rowid
|
|
213
|
+
JOIN entries ON entries.rowid=senses.entry_rowid
|
|
214
|
+
JOIN languages on entries.language_rowid=languages.rowid
|
|
215
|
+
WHERE sense_examples.sense_rowid = ?
|
|
216
|
+
ORDER BY example ASC"""
|
|
217
|
+
return Database.execute(sql_examples, (sense_rowid, )).fetchall()
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def fetch_concept_by_sense(sense_rowid):
|
|
222
|
+
"""
|
|
223
|
+
Retrieve the concept related to a sense
|
|
224
|
+
"""
|
|
225
|
+
sql_sense_concept=""" SELECT rowid, LOWER(pos), ili FROM synsets
|
|
226
|
+
WHERE rowid = ?"""
|
|
227
|
+
return Database.execute(sql_sense_concept, (sense_rowid, )).fetchone()
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
#-------- queries related to the class Lexeme
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def find_language_lexeme (lex_rowid):
|
|
234
|
+
"""
|
|
235
|
+
Retrieve the language of a lexeme
|
|
236
|
+
"""
|
|
237
|
+
sql_lex_lang=""" SELECT code FROM languages
|
|
238
|
+
JOIN entries ON entries.language_rowid = languages.rowid
|
|
239
|
+
WHERE entries.rowid = ?"""
|
|
240
|
+
return Database.execute(sql_lex_lang, (lex_rowid, )).fetchone()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def find_lemma(lex_rowid):
|
|
244
|
+
"""
|
|
245
|
+
Retrieve the lemma of a lexeme
|
|
246
|
+
"""
|
|
247
|
+
sql_lex_lemma=""" SELECT normalized_form FROM forms
|
|
248
|
+
WHERE rank=0 and entry_rowid= ?"""
|
|
249
|
+
return Database.execute(sql_lex_lemma, (lex_rowid, )).fetchone()
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def fetch_forms_by_lexeme(lex_rowid):
|
|
253
|
+
"""
|
|
254
|
+
Retrieve all the forms of a lexeme
|
|
255
|
+
"""
|
|
256
|
+
sql_lex_forms=""" SELECT form, entry_rowid, rank FROM forms
|
|
257
|
+
WHERE entry_rowid= ?
|
|
258
|
+
ORDER BY form ASC"""
|
|
259
|
+
return Database.execute(sql_lex_forms, (lex_rowid, )).fetchall()
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def fetch_senses_by_lexeme(lex_rowid):
|
|
263
|
+
"""
|
|
264
|
+
Retrieve all the senses of a lexeme
|
|
265
|
+
"""
|
|
266
|
+
sql_lex_senses="""SELECT rowid, synset_rowid, entry_rowid FROM senses
|
|
267
|
+
WHERE entry_rowid= ?
|
|
268
|
+
ORDER BY rowid ASC"""
|
|
269
|
+
return Database.execute(sql_lex_senses, (lex_rowid, )).fetchall()
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def fetch_concepts_by_lexeme(lex_rowid):
|
|
273
|
+
"""
|
|
274
|
+
Retrieve all the concepts related to a lexeme
|
|
275
|
+
"""
|
|
276
|
+
sql_lex_concepts="""SELECT synset_rowid, LOWER(synsets.pos), synsets.ili FROM senses
|
|
277
|
+
JOIN synsets ON synsets.rowid=senses.synset_rowid
|
|
278
|
+
WHERE senses.entry_rowid= ?
|
|
279
|
+
ORDER BY synsets.rowid ASC"""
|
|
280
|
+
return Database.execute(sql_lex_concepts, (lex_rowid, )).fetchall()
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
from typing import List, Optional,Tuple
|
|
2
|
+
from api import AbstractConcept, AbstractSense, AbstractLexeme, POS, AbstractAnnotatedString
|
|
3
|
+
import queries
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Concept(AbstractConcept):
|
|
7
|
+
"""
|
|
8
|
+
Implementation of the object Concept
|
|
9
|
+
"""
|
|
10
|
+
def __init__(self, data):
|
|
11
|
+
self.integer= data[0]
|
|
12
|
+
self.gram_cat = data[1]
|
|
13
|
+
self.identifier= data[2]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def __repr__(self):
|
|
17
|
+
return "Concept(id="+ str(self.integer)+')'
|
|
18
|
+
|
|
19
|
+
def index(self) -> str:
|
|
20
|
+
return self.identifier
|
|
21
|
+
|
|
22
|
+
def pos(self) -> POS:
|
|
23
|
+
return self.gram_cat
|
|
24
|
+
|
|
25
|
+
def definition(self, lang: str) -> Optional[AbstractAnnotatedString]:
|
|
26
|
+
row = queries.fetch_definition(self.integer, lang)
|
|
27
|
+
if row is None:
|
|
28
|
+
return None
|
|
29
|
+
else:
|
|
30
|
+
return AnnotatedString_Temp(row)
|
|
31
|
+
|
|
32
|
+
def senses(self, lang: Optional[str] = None) -> List[AbstractSense]:
|
|
33
|
+
rows= queries.fetch_senses_by_concept(self.integer,lang)
|
|
34
|
+
return [Sense(row) for row in rows]
|
|
35
|
+
|
|
36
|
+
def lexemes(self, lang: Optional[str] = None) -> List[AbstractLexeme]:
|
|
37
|
+
rows= queries.fetch_lexemes_by_concept(self.integer,lang)
|
|
38
|
+
return [Lexeme(row) for row in rows]
|
|
39
|
+
|
|
40
|
+
def hypernyms(self) -> List[AbstractConcept]:
|
|
41
|
+
rel_hyper= queries.fetch_related_synsets(self.integer,"5")
|
|
42
|
+
return [Concept(row) for row in rel_hyper]
|
|
43
|
+
|
|
44
|
+
def hyponyms(self) -> List[AbstractConcept]:
|
|
45
|
+
rel_hypo= queries.fetch_related_synsets(self.integer,"6")
|
|
46
|
+
return [Concept(row) for row in rel_hypo]
|
|
47
|
+
|
|
48
|
+
def meronyms(self) -> List[AbstractConcept]:
|
|
49
|
+
rel_mero=queries.fetch_related_synsets(self.integer,"7")
|
|
50
|
+
return [Concept(row) for row in rel_mero]
|
|
51
|
+
|
|
52
|
+
def holonyms(self) -> List[AbstractConcept]:
|
|
53
|
+
rel_holo=queries.fetch_related_synsets(self.integer,"8")
|
|
54
|
+
return [Concept(row) for row in rel_holo]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class Lexeme(AbstractLexeme):
|
|
61
|
+
"""
|
|
62
|
+
Implementation of the object Lexeme
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(self, data):
|
|
66
|
+
self.integer= data[0]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def __repr__(self):
|
|
70
|
+
return "Lexeme(id="+ str(self.integer)+")"
|
|
71
|
+
|
|
72
|
+
def index(self) -> str:
|
|
73
|
+
return str(self.integer)
|
|
74
|
+
|
|
75
|
+
def lang(self) -> str:
|
|
76
|
+
row = queries.find_language_lexeme (self.integer)
|
|
77
|
+
return (row[0])
|
|
78
|
+
|
|
79
|
+
def lemma(self) -> str:
|
|
80
|
+
row = queries.find_lemma (self.integer)
|
|
81
|
+
return (row[0])
|
|
82
|
+
|
|
83
|
+
def all_forms(self) -> List[str]:
|
|
84
|
+
rows = queries.fetch_forms_by_lexeme(self.integer)
|
|
85
|
+
results =[]
|
|
86
|
+
for row in rows:
|
|
87
|
+
results.append(row[0])
|
|
88
|
+
return results
|
|
89
|
+
|
|
90
|
+
def senses(self) -> List[AbstractSense]:
|
|
91
|
+
rows = queries.fetch_senses_by_lexeme(self.integer)
|
|
92
|
+
return [Sense(row) for row in rows]
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def concepts(self) -> List[AbstractConcept]:
|
|
96
|
+
rows = queries.fetch_concepts_by_lexeme(self.integer)
|
|
97
|
+
return [Concept(row) for row in rows]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class Sense(AbstractSense):
|
|
104
|
+
"""
|
|
105
|
+
Implementation of the object Sense
|
|
106
|
+
"""
|
|
107
|
+
def __init__(self, data):
|
|
108
|
+
self.integer= data[0]
|
|
109
|
+
self.linked_concept = data[1]
|
|
110
|
+
self.linked_entry = data[2]
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def __repr__(self):
|
|
114
|
+
return "Sense(id="+ str(self.integer)+")"
|
|
115
|
+
|
|
116
|
+
def index(self) -> str:
|
|
117
|
+
return str(self.integer)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def examples(self) -> List[AbstractAnnotatedString]:
|
|
121
|
+
row = queries.fetch_examples(self.integer)
|
|
122
|
+
if row is None:
|
|
123
|
+
return None
|
|
124
|
+
else:
|
|
125
|
+
return AnnotatedString(row)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def concept(self) -> AbstractConcept:
|
|
129
|
+
row = queries.fetch_concept_by_sense(self.linked_concept)
|
|
130
|
+
return Concept(row)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def lexeme(self) -> AbstractLexeme:
|
|
134
|
+
return Lexeme([self.linked_entry])
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def lang(self) -> str:
|
|
138
|
+
row = queries.find_language_lexeme (self.linked_entry)
|
|
139
|
+
return (row[0])
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
class AnnotatedString_Temp(AbstractAnnotatedString):
|
|
145
|
+
"""
|
|
146
|
+
Temporary class to deal with definitions
|
|
147
|
+
"""
|
|
148
|
+
def __init__(self, data):
|
|
149
|
+
self._text = data[0]
|
|
150
|
+
self._lang = data[1]
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def text(self) -> str:
|
|
154
|
+
return self._text
|
|
155
|
+
|
|
156
|
+
def lang(self) -> str:
|
|
157
|
+
return self._lang
|
|
158
|
+
|
|
159
|
+
def sense_offsets(self) -> List[Tuple[AbstractSense, int, int]]:
|
|
160
|
+
pass
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class AnnotatedString(AbstractAnnotatedString):
|
|
164
|
+
"""
|
|
165
|
+
Print examples and definitions as well as their annotations
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
def __init__(self, data):
|
|
169
|
+
|
|
170
|
+
self._text=[]
|
|
171
|
+
self._lang=[]
|
|
172
|
+
self._dic={}
|
|
173
|
+
for elem in data:
|
|
174
|
+
self._lang = elem[1]
|
|
175
|
+
self._text.append(elem[0])
|
|
176
|
+
if (elem[2], elem[3], elem[4]) not in self._dic:
|
|
177
|
+
self._dic[(elem[2], elem[3], elem[4])]=[[elem[-2], elem[-1]]]
|
|
178
|
+
else:
|
|
179
|
+
self._dic[(elem[2], elem[3], elem[4])].append([elem[-2], elem[-1]])
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def text(self) -> str:
|
|
184
|
+
return self._text
|
|
185
|
+
|
|
186
|
+
def lang(self) -> str:
|
|
187
|
+
return self._lang
|
|
188
|
+
|
|
189
|
+
def sense_offsets(self) -> List[Tuple[AbstractSense, int, int]]:
|
|
190
|
+
|
|
191
|
+
list_offsets=[]
|
|
192
|
+
for sense_index in self._dic:
|
|
193
|
+
for list_numbers in self._dic[sense_index]:
|
|
194
|
+
list_offsets.append(tuple([Sense(sense_index), list_numbers[0], list_numbers[1]]))
|
|
195
|
+
|
|
196
|
+
return list_offsets
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
|