Loglan-Core 0.2.5__tar.gz → 0.3.0__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.
- {Loglan-Core-0.2.5 → loglan_core-0.3.0/Loglan_Core.egg-info}/PKG-INFO +8 -5
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/Loglan_Core.egg-info/SOURCES.txt +1 -1
- {Loglan-Core-0.2.5/Loglan_Core.egg-info → loglan_core-0.3.0}/PKG-INFO +8 -5
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/README.md +5 -2
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/__init__.py +3 -1
- loglan_core-0.3.0/loglan_core/addons/base_selector.py +202 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/addons/definition_selector.py +16 -12
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/addons/export_word_converter.py +9 -2
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/addons/exporter.py +13 -10
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/addons/key_selector.py +37 -5
- loglan_core-0.3.0/loglan_core/addons/utils.py +61 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/addons/word_linker.py +6 -25
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/addons/word_selector.py +127 -38
- loglan_core-0.3.0/loglan_core/addons/word_sourcer.py +264 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/author.py +3 -12
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/base.py +19 -6
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/definition.py +7 -50
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/event.py +5 -58
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/key.py +4 -52
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/setting.py +1 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/syllable.py +7 -6
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/table_names.py +0 -3
- loglan_core-0.3.0/loglan_core/type.py +66 -0
- loglan_core-0.3.0/loglan_core/word.py +155 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/word_spell.py +1 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/setup.py +2 -3
- Loglan-Core-0.2.5/loglan_core/addons/base_selector.py +0 -79
- Loglan-Core-0.2.5/loglan_core/addons/word_sourcer.py +0 -174
- Loglan-Core-0.2.5/loglan_core/type.py +0 -109
- Loglan-Core-0.2.5/loglan_core/word.py +0 -340
- Loglan-Core-0.2.5/loglan_core/word_source.py +0 -71
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/LICENSE +0 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/Loglan_Core.egg-info/dependency_links.txt +0 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/Loglan_Core.egg-info/requires.txt +0 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/Loglan_Core.egg-info/top_level.txt +0 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/addons/__init__.py +0 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/loglan_core/connect_tables.py +0 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/pyproject.toml +0 -0
- {Loglan-Core-0.2.5 → loglan_core-0.3.0}/setup.cfg +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: Loglan-Core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Loglan Dictionary Database Model for SQLAlchemy
|
|
5
5
|
Home-page: https://github.com/torrua/loglan_core
|
|
6
|
-
Download-URL: https://github.com/torrua/loglan_core/archive/0.
|
|
6
|
+
Download-URL: https://github.com/torrua/loglan_core/archive/0.3.0.tar.gz
|
|
7
7
|
Author: torrua
|
|
8
8
|
Author-email: torrua@gmail.com
|
|
9
9
|
License: MIT
|
|
10
10
|
Keywords: Loglan,Dictionary,Database,Model,LOD
|
|
11
|
-
Classifier: Development Status ::
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: Intended Audience :: Science/Research
|
|
14
14
|
Classifier: Topic :: Database
|
|
@@ -26,14 +26,17 @@ Requires-Dist: sqlalchemy>=2.0.21
|
|
|
26
26
|

|
|
27
27
|

|
|
28
28
|

|
|
29
|
-
|
|
29
|
+

|
|
30
30
|
[](https://github.com/torrua/loglan_core/actions/workflows/pytest.yml)
|
|
31
|
-

|
|
32
|
+

|
|
33
|
+
|
|
32
34
|

|
|
33
35
|

|
|
34
36
|

|
|
35
37
|
|
|
36
38
|
|
|
39
|
+
|
|
37
40
|
# SQLAlchemy Database Model for Loglan Dictionary
|
|
38
41
|
|
|
39
42
|
This project represent a SQLAlchemy database model for the dictionary of [constructed language Loglan](http://www.loglan.org/).
|
|
@@ -20,7 +20,6 @@ loglan_core/syllable.py
|
|
|
20
20
|
loglan_core/table_names.py
|
|
21
21
|
loglan_core/type.py
|
|
22
22
|
loglan_core/word.py
|
|
23
|
-
loglan_core/word_source.py
|
|
24
23
|
loglan_core/word_spell.py
|
|
25
24
|
loglan_core/addons/__init__.py
|
|
26
25
|
loglan_core/addons/base_selector.py
|
|
@@ -28,6 +27,7 @@ loglan_core/addons/definition_selector.py
|
|
|
28
27
|
loglan_core/addons/export_word_converter.py
|
|
29
28
|
loglan_core/addons/exporter.py
|
|
30
29
|
loglan_core/addons/key_selector.py
|
|
30
|
+
loglan_core/addons/utils.py
|
|
31
31
|
loglan_core/addons/word_linker.py
|
|
32
32
|
loglan_core/addons/word_selector.py
|
|
33
33
|
loglan_core/addons/word_sourcer.py
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: Loglan-Core
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Loglan Dictionary Database Model for SQLAlchemy
|
|
5
5
|
Home-page: https://github.com/torrua/loglan_core
|
|
6
|
-
Download-URL: https://github.com/torrua/loglan_core/archive/0.
|
|
6
|
+
Download-URL: https://github.com/torrua/loglan_core/archive/0.3.0.tar.gz
|
|
7
7
|
Author: torrua
|
|
8
8
|
Author-email: torrua@gmail.com
|
|
9
9
|
License: MIT
|
|
10
10
|
Keywords: Loglan,Dictionary,Database,Model,LOD
|
|
11
|
-
Classifier: Development Status ::
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: Intended Audience :: Science/Research
|
|
14
14
|
Classifier: Topic :: Database
|
|
@@ -26,14 +26,17 @@ Requires-Dist: sqlalchemy>=2.0.21
|
|
|
26
26
|

|
|
27
27
|

|
|
28
28
|

|
|
29
|
-
|
|
29
|
+

|
|
30
30
|
[](https://github.com/torrua/loglan_core/actions/workflows/pytest.yml)
|
|
31
|
-

|
|
32
|
+

|
|
33
|
+
|
|
32
34
|

|
|
33
35
|

|
|
34
36
|

|
|
35
37
|
|
|
36
38
|
|
|
39
|
+
|
|
37
40
|
# SQLAlchemy Database Model for Loglan Dictionary
|
|
38
41
|
|
|
39
42
|
This project represent a SQLAlchemy database model for the dictionary of [constructed language Loglan](http://www.loglan.org/).
|
|
@@ -3,14 +3,17 @@
|
|
|
3
3
|

|
|
4
4
|

|
|
5
5
|

|
|
6
|
-
|
|
6
|
+

|
|
7
7
|
[](https://github.com/torrua/loglan_core/actions/workflows/pytest.yml)
|
|
8
|
-

|
|
9
|
+

|
|
10
|
+
|
|
9
11
|

|
|
10
12
|

|
|
11
13
|

|
|
12
14
|
|
|
13
15
|
|
|
16
|
+
|
|
14
17
|
# SQLAlchemy Database Model for Loglan Dictionary
|
|
15
18
|
|
|
16
19
|
This project represent a SQLAlchemy database model for the dictionary of [constructed language Loglan](http://www.loglan.org/).
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Main point for export DB models
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
# fmt: off
|
|
6
|
+
|
|
5
7
|
__author__ = "torrua"
|
|
6
8
|
__copyright__ = "Copyright 2024, loglan_core project"
|
|
7
9
|
__email__ = "torrua@gmail.com"
|
|
@@ -19,7 +21,7 @@ from loglan_core.setting import BaseSetting as Setting
|
|
|
19
21
|
from loglan_core.syllable import BaseSyllable as Syllable
|
|
20
22
|
from loglan_core.type import BaseType as Type
|
|
21
23
|
from loglan_core.word import BaseWord as Word
|
|
22
|
-
from loglan_core.word_source import BaseWordSource as WordSource
|
|
23
24
|
from loglan_core.word_spell import BaseWordSpell as WordSpell
|
|
25
|
+
|
|
24
26
|
from loglan_core.base import BaseModel as Base
|
|
25
27
|
from loglan_core.addons.word_selector import WordSelector
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides a base selector for SQLAlchemy
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Any, Type
|
|
8
|
+
from typing_extensions import Self
|
|
9
|
+
|
|
10
|
+
from sqlalchemy import Select, BinaryExpression
|
|
11
|
+
from sqlalchemy.orm import Session, InstrumentedAttribute
|
|
12
|
+
|
|
13
|
+
from loglan_core.base import BaseModel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class BaseSelector(Select): # pylint: disable=too-many-ancestors
|
|
17
|
+
"""
|
|
18
|
+
A custom base selector that inherits from SQLAlchemy's Select class.
|
|
19
|
+
This class provides methods to execute a session and fetch results
|
|
20
|
+
in different ways. It also provides a way to fetch many results.
|
|
21
|
+
|
|
22
|
+
Methods:
|
|
23
|
+
--------
|
|
24
|
+
execute(session: Session) -> ResultProxy:
|
|
25
|
+
Executes the session and returns the result.
|
|
26
|
+
|
|
27
|
+
all(session: Session) -> List[ResultRow]:
|
|
28
|
+
Executes the session and returns all the results.
|
|
29
|
+
|
|
30
|
+
scalar(session: Session) -> Any:
|
|
31
|
+
Executes the session and returns a scalar result.
|
|
32
|
+
|
|
33
|
+
fetchmany(session: Session, size: int | None = None) -> List[ResultRow]:
|
|
34
|
+
Executes the session and fetches a specified number of results.
|
|
35
|
+
|
|
36
|
+
condition_by_attribute(
|
|
37
|
+
class_: Type[BaseModel],
|
|
38
|
+
attr: InstrumentedAttribute | str,
|
|
39
|
+
value: Any,
|
|
40
|
+
is_sqlite: bool = False,
|
|
41
|
+
case_sensitive: bool = False,
|
|
42
|
+
) -> BinaryExpression:
|
|
43
|
+
Creates a filter to select items by a specific attribute value.
|
|
44
|
+
Support wildcard and case-sensitive search.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def execute(self, session: Session):
|
|
48
|
+
"""
|
|
49
|
+
Executes the given session and returns the result.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
session (Session): SQLAlchemy Session object.
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
ResultProxy: The result of the executed session.
|
|
56
|
+
"""
|
|
57
|
+
return session.execute(self)
|
|
58
|
+
|
|
59
|
+
def all(self, session: Session):
|
|
60
|
+
"""
|
|
61
|
+
Executes the given session and returns all the results as a list.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
session (Session): SQLAlchemy Session object.
|
|
65
|
+
|
|
66
|
+
Returns:
|
|
67
|
+
List[ResultRow]: All the results of the executed session.
|
|
68
|
+
"""
|
|
69
|
+
return self.execute(session).scalars().all()
|
|
70
|
+
|
|
71
|
+
def scalar(self, session: Session):
|
|
72
|
+
"""
|
|
73
|
+
Executes the given session and returns a scalar result.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
session (Session): SQLAlchemy Session object.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Any: The scalar result of the executed session.
|
|
80
|
+
"""
|
|
81
|
+
return self.execute(session).scalar()
|
|
82
|
+
|
|
83
|
+
def fetchmany(self, session: Session, size: int | None = None):
|
|
84
|
+
"""
|
|
85
|
+
Executes the given session and fetches a specified number of results.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
session (Session): SQLAlchemy Session object.
|
|
89
|
+
size (int, optional): Number of results to fetch. If None, fetches all results.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
List[ResultRow]: The fetched results.
|
|
93
|
+
"""
|
|
94
|
+
return self.execute(session).scalars().fetchmany(size)
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def condition_by_attribute(
|
|
98
|
+
cls,
|
|
99
|
+
class_: Type[BaseModel],
|
|
100
|
+
attr: InstrumentedAttribute | str,
|
|
101
|
+
value: Any,
|
|
102
|
+
is_sqlite: bool = False,
|
|
103
|
+
case_sensitive: bool = False,
|
|
104
|
+
) -> BinaryExpression:
|
|
105
|
+
"""
|
|
106
|
+
Applies a filter to select words by a specific attribute value.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
class_ (BaseModel): The class to select from.
|
|
110
|
+
attr (str): The attribute to filter by.
|
|
111
|
+
value (Any): The value of the attribute to filter by.
|
|
112
|
+
is_sqlite (bool): If SQLite is being used. Defaults to False.
|
|
113
|
+
case_sensitive (bool): Whether the search should be case-sensitive.
|
|
114
|
+
Defaults to False.
|
|
115
|
+
Returns:
|
|
116
|
+
BaseSelector: A query with the filter applied.
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
cls._is_class_acceptable(class_)
|
|
120
|
+
attr = cls._get_attr(class_, attr)
|
|
121
|
+
|
|
122
|
+
value = str(value).replace("*", "%")
|
|
123
|
+
|
|
124
|
+
if case_sensitive:
|
|
125
|
+
return attr.op("GLOB")(value) if is_sqlite else attr.like(value)
|
|
126
|
+
return attr.ilike(value)
|
|
127
|
+
|
|
128
|
+
@staticmethod
|
|
129
|
+
def _get_attr(
|
|
130
|
+
class_: Type[BaseModel],
|
|
131
|
+
attr: InstrumentedAttribute | str,
|
|
132
|
+
) -> InstrumentedAttribute:
|
|
133
|
+
"""
|
|
134
|
+
Gets the attribute from the class.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
class_ (BaseModel): The class to get the attribute from.
|
|
138
|
+
attr (str | InstrumentedAttribute): The attribute to get.
|
|
139
|
+
|
|
140
|
+
Raises:
|
|
141
|
+
AttributeError: If the attribute is not found in the class.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
InstrumentedAttribute: The attribute from the class.
|
|
145
|
+
"""
|
|
146
|
+
if isinstance(attr, str):
|
|
147
|
+
try:
|
|
148
|
+
return getattr(class_, attr)
|
|
149
|
+
except AttributeError as exc:
|
|
150
|
+
raise AttributeError(
|
|
151
|
+
f"Provided attribute={attr} is not an attribute of {class_}"
|
|
152
|
+
) from exc
|
|
153
|
+
return attr
|
|
154
|
+
|
|
155
|
+
@staticmethod
|
|
156
|
+
def _is_class_acceptable(class_: Type[BaseModel]):
|
|
157
|
+
"""
|
|
158
|
+
Checks if the class is an instance of BaseModel or its child.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
class_ (Type[BaseModel]): The class to check.
|
|
162
|
+
|
|
163
|
+
Raises:
|
|
164
|
+
ValueError: If the class is not an instance of BaseModel or its child.
|
|
165
|
+
"""
|
|
166
|
+
if not issubclass(class_, BaseModel):
|
|
167
|
+
raise ValueError(
|
|
168
|
+
f"Provided class_={class_} is not a {BaseModel} or its child"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def by_attrs(
|
|
172
|
+
self,
|
|
173
|
+
class_: Type[BaseModel],
|
|
174
|
+
is_sqlite: bool = False,
|
|
175
|
+
case_sensitive: bool = False,
|
|
176
|
+
**kwargs,
|
|
177
|
+
) -> Self:
|
|
178
|
+
"""
|
|
179
|
+
Selects all words by a set of attributes.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
class_ (Type[BaseModel]): The class to select from.
|
|
183
|
+
is_sqlite (bool): If SQLite is being used. Defaults to False.
|
|
184
|
+
case_sensitive (bool): Whether the search should be case-sensitive.
|
|
185
|
+
Defaults to False.
|
|
186
|
+
**kwargs: A set of attributes to filter by.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
BaseSelector: A query with the filter applied.
|
|
190
|
+
"""
|
|
191
|
+
return self.where(
|
|
192
|
+
*{
|
|
193
|
+
self.condition_by_attribute(
|
|
194
|
+
class_,
|
|
195
|
+
k,
|
|
196
|
+
v,
|
|
197
|
+
is_sqlite=is_sqlite,
|
|
198
|
+
case_sensitive=case_sensitive,
|
|
199
|
+
)
|
|
200
|
+
for k, v in kwargs.items()
|
|
201
|
+
}
|
|
202
|
+
)
|
|
@@ -11,9 +11,16 @@ Classes:
|
|
|
11
11
|
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
|
-
from
|
|
14
|
+
from typing import cast
|
|
15
|
+
|
|
16
|
+
from sqlalchemy import select, true
|
|
15
17
|
|
|
16
18
|
from loglan_core.addons.base_selector import BaseSelector
|
|
19
|
+
from loglan_core.addons.utils import (
|
|
20
|
+
filter_word_by_event_id,
|
|
21
|
+
filter_key_by_word_cs,
|
|
22
|
+
filter_key_by_language,
|
|
23
|
+
)
|
|
17
24
|
from loglan_core.connect_tables import t_connect_keys
|
|
18
25
|
from loglan_core.definition import BaseDefinition
|
|
19
26
|
from loglan_core.key import BaseKey
|
|
@@ -86,10 +93,10 @@ class DefinitionSelector(BaseSelector): # pylint: disable=too-many-ancestors
|
|
|
86
93
|
select(self.class_.id)
|
|
87
94
|
.join(t_connect_keys)
|
|
88
95
|
.join(BaseWord)
|
|
89
|
-
.where(
|
|
96
|
+
.where(filter_word_by_event_id(event_id))
|
|
90
97
|
.scalar_subquery()
|
|
91
98
|
)
|
|
92
|
-
return self.where(self.class_.id.in_(subquery))
|
|
99
|
+
return cast(DefinitionSelector, self.where(self.class_.id.in_(subquery)))
|
|
93
100
|
|
|
94
101
|
def by_key(
|
|
95
102
|
self,
|
|
@@ -111,17 +118,13 @@ class DefinitionSelector(BaseSelector): # pylint: disable=too-many-ancestors
|
|
|
111
118
|
"""
|
|
112
119
|
|
|
113
120
|
search_key = key.word if isinstance(key, BaseKey) else str(key)
|
|
114
|
-
filter_key =
|
|
115
|
-
|
|
116
|
-
)
|
|
117
|
-
filter_language = BaseKey.filter_by_language(
|
|
121
|
+
filter_key = filter_key_by_word_cs(search_key, case_sensitive, self.is_sqlite)
|
|
122
|
+
filter_language = filter_key_by_language(
|
|
118
123
|
key.language if isinstance(key, BaseKey) else language
|
|
119
124
|
)
|
|
120
125
|
|
|
121
|
-
statement = self.join(self.class_.
|
|
122
|
-
|
|
123
|
-
)
|
|
124
|
-
return statement.distinct()
|
|
126
|
+
statement = self.join(self.class_.keys).filter(filter_key, filter_language)
|
|
127
|
+
return cast(DefinitionSelector, statement.distinct())
|
|
125
128
|
|
|
126
129
|
def by_language(self, language: str | None = None) -> DefinitionSelector:
|
|
127
130
|
"""
|
|
@@ -134,4 +137,5 @@ class DefinitionSelector(BaseSelector): # pylint: disable=too-many-ancestors
|
|
|
134
137
|
Returns:
|
|
135
138
|
DefinitionSelector: The filtered DefinitionSelector instance.
|
|
136
139
|
"""
|
|
137
|
-
|
|
140
|
+
filter_language = self.class_.language == language if language else true()
|
|
141
|
+
return cast(DefinitionSelector, self.filter(filter_language))
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
This module contains ExportWordConverter for Word model of LOD.
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from loglan_core.word import BaseWord
|
|
5
6
|
|
|
6
7
|
|
|
@@ -59,7 +60,9 @@ class ExportWordConverter:
|
|
|
59
60
|
Returns:
|
|
60
61
|
str: A string with the names of the complexes separated by a vertical bar.
|
|
61
62
|
"""
|
|
62
|
-
return " | ".join(
|
|
63
|
+
return " | ".join(
|
|
64
|
+
cpx.name for cpx in self.word.derivatives if cpx.type.group == "Cpx"
|
|
65
|
+
)
|
|
63
66
|
|
|
64
67
|
@property
|
|
65
68
|
def e_affixes(self) -> str:
|
|
@@ -69,7 +72,11 @@ class ExportWordConverter:
|
|
|
69
72
|
Returns:
|
|
70
73
|
str: A string containing all affixes of the word with hyphens removed.
|
|
71
74
|
"""
|
|
72
|
-
return " ".join(
|
|
75
|
+
return " ".join(
|
|
76
|
+
afx.name.replace("-", "")
|
|
77
|
+
for afx in self.word.derivatives
|
|
78
|
+
if afx.type.type_x == "Affix"
|
|
79
|
+
).strip()
|
|
73
80
|
|
|
74
81
|
@property
|
|
75
82
|
def e_djifoa(self) -> str:
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
This module contains an "Export extensions" for LOD dictionary SQL model.
|
|
3
3
|
Add export() function to db object for returning its text string presentation.
|
|
4
4
|
"""
|
|
5
|
-
from typing import Iterable, Callable, Type
|
|
6
5
|
|
|
6
|
+
from typing import Iterable, Callable, Type
|
|
7
7
|
|
|
8
8
|
from loglan_core.addons.export_word_converter import ExportWordConverter
|
|
9
9
|
from loglan_core.author import BaseAuthor
|
|
@@ -42,6 +42,9 @@ class Exporter:
|
|
|
42
42
|
ValueError: If the object type is not supported for export.
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
|
+
FORMAT_DATE_EVENT = "%m/%d/%Y"
|
|
46
|
+
FORMAT_DATE_SETTING = "%d.%m.%Y %H:%M:%S"
|
|
47
|
+
|
|
45
48
|
@classmethod
|
|
46
49
|
def export(cls, obj, separator: str = DEFAULT_SEPARATOR) -> str:
|
|
47
50
|
"""
|
|
@@ -102,8 +105,8 @@ class Exporter:
|
|
|
102
105
|
"""
|
|
103
106
|
return obj.abbreviation, obj.full_name, obj.notes
|
|
104
107
|
|
|
105
|
-
@
|
|
106
|
-
def export_event(obj: BaseEvent) -> tuple:
|
|
108
|
+
@classmethod
|
|
109
|
+
def export_event(cls, obj: BaseEvent) -> tuple:
|
|
107
110
|
"""
|
|
108
111
|
Prepare Event data for exporting to text file
|
|
109
112
|
|
|
@@ -113,7 +116,7 @@ class Exporter:
|
|
|
113
116
|
return (
|
|
114
117
|
obj.event_id,
|
|
115
118
|
obj.name,
|
|
116
|
-
obj.date.strftime(
|
|
119
|
+
obj.date.strftime(cls.FORMAT_DATE_EVENT),
|
|
117
120
|
obj.definition,
|
|
118
121
|
obj.annotation,
|
|
119
122
|
obj.suffix,
|
|
@@ -127,10 +130,10 @@ class Exporter:
|
|
|
127
130
|
Returns:
|
|
128
131
|
tuple: elements for export
|
|
129
132
|
"""
|
|
130
|
-
return obj.name, obj.
|
|
133
|
+
return obj.name, obj.type_, str(obj.allowed)
|
|
131
134
|
|
|
132
|
-
@
|
|
133
|
-
def export_setting(obj: BaseSetting) -> tuple:
|
|
135
|
+
@classmethod
|
|
136
|
+
def export_setting(cls, obj: BaseSetting) -> tuple:
|
|
134
137
|
"""
|
|
135
138
|
Prepare Setting data for exporting to text file
|
|
136
139
|
|
|
@@ -138,7 +141,7 @@ class Exporter:
|
|
|
138
141
|
tuple: elements for export
|
|
139
142
|
"""
|
|
140
143
|
return (
|
|
141
|
-
obj.date.strftime(
|
|
144
|
+
obj.date.strftime(cls.FORMAT_DATE_SETTING),
|
|
142
145
|
obj.db_version,
|
|
143
146
|
obj.last_word_id,
|
|
144
147
|
obj.db_release,
|
|
@@ -153,7 +156,7 @@ class Exporter:
|
|
|
153
156
|
tuple: elements for export
|
|
154
157
|
"""
|
|
155
158
|
return (
|
|
156
|
-
obj.
|
|
159
|
+
obj.type_,
|
|
157
160
|
obj.type_x,
|
|
158
161
|
obj.group,
|
|
159
162
|
str(obj.parentable),
|
|
@@ -175,7 +178,7 @@ class Exporter:
|
|
|
175
178
|
origin = ewc.stringer(obj.origin)
|
|
176
179
|
return (
|
|
177
180
|
obj.id_old,
|
|
178
|
-
obj.type.
|
|
181
|
+
obj.type.type_,
|
|
179
182
|
obj.type.type_x,
|
|
180
183
|
ewc.e_affixes,
|
|
181
184
|
match,
|
|
@@ -23,9 +23,16 @@ This allows for flexible and powerful querying of keys in a codebase.
|
|
|
23
23
|
|
|
24
24
|
from __future__ import annotations
|
|
25
25
|
|
|
26
|
+
from typing import cast
|
|
27
|
+
|
|
26
28
|
from sqlalchemy import select
|
|
27
29
|
|
|
28
30
|
from loglan_core.addons.base_selector import BaseSelector
|
|
31
|
+
from loglan_core.addons.utils import (
|
|
32
|
+
filter_word_by_event_id,
|
|
33
|
+
filter_key_by_word_cs,
|
|
34
|
+
filter_key_by_language,
|
|
35
|
+
)
|
|
29
36
|
from loglan_core.connect_tables import t_connect_keys
|
|
30
37
|
from loglan_core.definition import BaseDefinition
|
|
31
38
|
from loglan_core.key import BaseKey
|
|
@@ -87,10 +94,10 @@ class KeySelector(BaseSelector): # pylint: disable=too-many-ancestors
|
|
|
87
94
|
.join(t_connect_keys)
|
|
88
95
|
.join(BaseDefinition)
|
|
89
96
|
.join(BaseWord)
|
|
90
|
-
.where(
|
|
97
|
+
.where(filter_word_by_event_id(event_id))
|
|
91
98
|
.scalar_subquery()
|
|
92
99
|
)
|
|
93
|
-
return self.where(self.class_.id.in_(subquery))
|
|
100
|
+
return cast(KeySelector, self.where(self.class_.id.in_(subquery)))
|
|
94
101
|
|
|
95
102
|
def by_key(self, key: str, case_sensitive: bool = False) -> KeySelector:
|
|
96
103
|
"""
|
|
@@ -104,8 +111,9 @@ class KeySelector(BaseSelector): # pylint: disable=too-many-ancestors
|
|
|
104
111
|
Returns:
|
|
105
112
|
KeySelector: The filtered KeySelector instance.
|
|
106
113
|
"""
|
|
107
|
-
return
|
|
108
|
-
|
|
114
|
+
return cast(
|
|
115
|
+
KeySelector,
|
|
116
|
+
self.where(filter_key_by_word_cs(key, case_sensitive, self.is_sqlite)),
|
|
109
117
|
)
|
|
110
118
|
|
|
111
119
|
def by_language(self, language: str | None = None) -> KeySelector:
|
|
@@ -119,4 +127,28 @@ class KeySelector(BaseSelector): # pylint: disable=too-many-ancestors
|
|
|
119
127
|
Returns:
|
|
120
128
|
KeySelector: The filtered KeySelector instance.
|
|
121
129
|
"""
|
|
122
|
-
return self.where(
|
|
130
|
+
return cast(KeySelector, self.where(filter_key_by_language(language)))
|
|
131
|
+
|
|
132
|
+
def by_word_id(self, word_id: int) -> KeySelector:
|
|
133
|
+
"""
|
|
134
|
+
Filters the keys by the given word ID.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
word_id (int): The identifier of the word to filter by.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
KeySelector: The filtered KeySelector instance.
|
|
141
|
+
|
|
142
|
+
Keep in mind that duplicated keys from related definitions
|
|
143
|
+
will be counted with ```.count()``` but excluded from ```.all()``` request
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
return cast(
|
|
147
|
+
KeySelector,
|
|
148
|
+
self.distinct()
|
|
149
|
+
.join(t_connect_keys)
|
|
150
|
+
.join(BaseDefinition, BaseDefinition.id == t_connect_keys.c.DID)
|
|
151
|
+
.join(BaseWord, BaseWord.id == BaseDefinition.word_id)
|
|
152
|
+
.filter(BaseWord.id == word_id)
|
|
153
|
+
.order_by(BaseKey.word.asc()),
|
|
154
|
+
)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides utility functions for the loglan_core package.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from sqlalchemy import select, true, func
|
|
8
|
+
from sqlalchemy.sql.elements import BinaryExpression
|
|
9
|
+
from sqlalchemy.sql.elements import BooleanClauseList
|
|
10
|
+
from sqlalchemy.sql.expression import ColumnElement
|
|
11
|
+
|
|
12
|
+
from loglan_core.event import BaseEvent
|
|
13
|
+
from loglan_core.key import BaseKey
|
|
14
|
+
from loglan_core.word import BaseWord
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def filter_word_by_event_id(event_id: int | None) -> BooleanClauseList:
|
|
18
|
+
"""
|
|
19
|
+
Returns a filter condition to select words associated with a specific event.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
event_id: The id of the event to filter by. Defaults to None.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
BooleanClauseList: A filter condition to select words associated with a specific event.
|
|
26
|
+
"""
|
|
27
|
+
latest_id = select(func.max(BaseEvent.event_id)).scalar_subquery()
|
|
28
|
+
event_id_filter = event_id or latest_id
|
|
29
|
+
start_id_condition = BaseWord.event_start_id <= event_id_filter
|
|
30
|
+
end_id_condition = (
|
|
31
|
+
BaseWord.event_end_id > event_id_filter
|
|
32
|
+
) | BaseWord.event_end_id.is_(None)
|
|
33
|
+
return start_id_condition & end_id_condition
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def filter_key_by_word_cs(
|
|
37
|
+
key: str,
|
|
38
|
+
case_sensitive: bool = False,
|
|
39
|
+
is_sqlite: bool = False,
|
|
40
|
+
) -> BinaryExpression:
|
|
41
|
+
"""case sensitive name filter"""
|
|
42
|
+
key = str(key).replace("*", "%")
|
|
43
|
+
return (
|
|
44
|
+
(BaseKey.word.op("GLOB")(key) if is_sqlite else BaseKey.word.like(key))
|
|
45
|
+
if case_sensitive
|
|
46
|
+
else BaseKey.word.ilike(key)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def filter_key_by_language(language: str | None = None) -> ColumnElement[bool]:
|
|
51
|
+
"""
|
|
52
|
+
Filter the language of the base key.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
language (str or None): The language to filter by.
|
|
56
|
+
If None, no language filter will be applied.
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
ColumnElement[bool]: A filter condition for the base key's language.
|
|
60
|
+
"""
|
|
61
|
+
return (BaseKey.language == language) if language else true()
|