Loglan-Core 0.4.3__tar.gz → 0.4.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. {loglan_core-0.4.3 → loglan_core-0.4.5/Loglan_Core.egg-info}/PKG-INFO +2 -2
  2. {loglan_core-0.4.3/Loglan_Core.egg-info → loglan_core-0.4.5}/PKG-INFO +2 -2
  3. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/base_selector.py +73 -30
  4. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/word_selector.py +1 -1
  5. {loglan_core-0.4.3 → loglan_core-0.4.5}/setup.py +1 -1
  6. {loglan_core-0.4.3 → loglan_core-0.4.5}/LICENSE +0 -0
  7. {loglan_core-0.4.3 → loglan_core-0.4.5}/Loglan_Core.egg-info/SOURCES.txt +0 -0
  8. {loglan_core-0.4.3 → loglan_core-0.4.5}/Loglan_Core.egg-info/dependency_links.txt +0 -0
  9. {loglan_core-0.4.3 → loglan_core-0.4.5}/Loglan_Core.egg-info/requires.txt +0 -0
  10. {loglan_core-0.4.3 → loglan_core-0.4.5}/Loglan_Core.egg-info/top_level.txt +0 -0
  11. {loglan_core-0.4.3 → loglan_core-0.4.5}/README.md +0 -0
  12. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/__init__.py +0 -0
  13. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/__init__.py +0 -0
  14. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/definition_selector.py +0 -0
  15. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/export_word_converter.py +0 -0
  16. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/exporter.py +0 -0
  17. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/key_selector.py +0 -0
  18. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/utils.py +0 -0
  19. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/word_linker.py +0 -0
  20. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/addons/word_sourcer.py +0 -0
  21. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/author.py +0 -0
  22. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/base.py +0 -0
  23. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/connect_tables.py +0 -0
  24. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/definition.py +0 -0
  25. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/event.py +0 -0
  26. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/key.py +0 -0
  27. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/setting.py +0 -0
  28. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/syllable.py +0 -0
  29. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/table_names.py +0 -0
  30. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/type.py +0 -0
  31. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/word.py +0 -0
  32. {loglan_core-0.4.3 → loglan_core-0.4.5}/loglan_core/word_spell.py +0 -0
  33. {loglan_core-0.4.3 → loglan_core-0.4.5}/pyproject.toml +0 -0
  34. {loglan_core-0.4.3 → loglan_core-0.4.5}/setup.cfg +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Loglan-Core
3
- Version: 0.4.3
3
+ Version: 0.4.5
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.4.3.tar.gz
6
+ Download-URL: https://github.com/torrua/loglan_core/archive/0.4.5.tar.gz
7
7
  Author: torrua
8
8
  Author-email: torrua@gmail.com
9
9
  License: MIT
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: Loglan-Core
3
- Version: 0.4.3
3
+ Version: 0.4.5
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.4.3.tar.gz
6
+ Download-URL: https://github.com/torrua/loglan_core/archive/0.4.5.tar.gz
7
7
  Author: torrua
8
8
  Author-email: torrua@gmail.com
9
9
  License: MIT
@@ -8,6 +8,7 @@ from typing import Type, Iterable, Any
8
8
 
9
9
  from sqlalchemy import select, Select
10
10
  from sqlalchemy.orm import Session, InstrumentedAttribute, joinedload
11
+ from sqlalchemy.types import String
11
12
  from typing_extensions import Self
12
13
 
13
14
  from loglan_core.base import BaseModel
@@ -62,8 +63,7 @@ class BaseSelector: # pylint: disable=too-many-ancestors
62
63
  self.case_sensitive = case_sensitive
63
64
 
64
65
  def execute(self, session: Session):
65
- """
66
- Executes the given session and returns the result.
66
+ """Executes the given session and returns the result.
67
67
 
68
68
  Args:
69
69
  session (Session): SQLAlchemy Session object.
@@ -74,8 +74,7 @@ class BaseSelector: # pylint: disable=too-many-ancestors
74
74
  return session.execute(self._statement)
75
75
 
76
76
  def all(self, session: Session):
77
- """
78
- Executes the given session and returns all the results as a list.
77
+ """Executes the given session and returns all the results as a list.
79
78
 
80
79
  Args:
81
80
  session (Session): SQLAlchemy Session object.
@@ -86,8 +85,7 @@ class BaseSelector: # pylint: disable=too-many-ancestors
86
85
  return session.execute(self._statement).scalars().all()
87
86
 
88
87
  def scalar(self, session: Session):
89
- """
90
- Executes the given session and returns a scalar result.
88
+ """Executes the given session and returns a scalar result.
91
89
 
92
90
  Args:
93
91
  session (Session): SQLAlchemy Session object.
@@ -98,8 +96,7 @@ class BaseSelector: # pylint: disable=too-many-ancestors
98
96
  return session.execute(self._statement).scalar()
99
97
 
100
98
  def fetchmany(self, session: Session, size: int | None = None):
101
- """
102
- Executes the given session and fetches a specified number of results.
99
+ """Executes the given session and fetches a specified number of results.
103
100
 
104
101
  Args:
105
102
  session (Session): SQLAlchemy Session object.
@@ -204,15 +201,47 @@ class BaseSelector: # pylint: disable=too-many-ancestors
204
201
  self._statement = self._statement.where(*args)
205
202
  return self
206
203
 
207
- def _generate_column_condition(self, key: str | InstrumentedAttribute, value: Any):
208
- column = getattr(self.model, key, None) if isinstance(key, str) else key
209
- if column is None:
210
- raise AttributeError(f"Model {self.model} has no attribute {key}")
204
+ def where_like(self, **kwargs) -> Self:
205
+ """Filter results based on arbitrary keyword arguments.
206
+ Use internal method `_generate_column_condition` to generate
207
+ the condition based on settings provided by Selector instance
208
+ like (is_sqlite, case_sensitive).
209
+
210
+ Args:
211
+ **kwargs: Column-value pairs to filter by.
211
212
 
212
- value = str(value).replace("*", "%")
213
- if self.case_sensitive:
214
- return column.op("GLOB")(value) if self.is_sqlite else column.like(value)
215
- return column.ilike(value)
213
+ Returns:
214
+ Self: The current instance for method chaining.
215
+ """
216
+ for key, value in kwargs.items():
217
+ self._statement = self._statement.where(self.get_like_condition(key, value))
218
+ return self
219
+
220
+ def get_like_condition(self, key: str | InstrumentedAttribute, value: Any):
221
+ """Generate the condition based on settings provided by Selector instance
222
+ like (is_sqlite, case_sensitive).
223
+
224
+ Args:
225
+ key (str | InstrumentedAttribute): The key of the column to filter by.
226
+ value (Any): The value to filter by.
227
+
228
+ Returns:
229
+ Condition: The SQLAlchemy condition to filter by.
230
+ """
231
+ column = self._get_column(key)
232
+
233
+ if not isinstance(column.type, String):
234
+ return column == value
235
+
236
+ value = value.replace("*", "%")
237
+
238
+ if not self.case_sensitive:
239
+ return column.ilike(value)
240
+
241
+ if self.is_sqlite:
242
+ return column.op("GLOB")(value)
243
+
244
+ return column.like(value)
216
245
 
217
246
  def get_statement(self) -> Select:
218
247
  """Get the current SQLAlchemy _statement.
@@ -233,21 +262,8 @@ class BaseSelector: # pylint: disable=too-many-ancestors
233
262
  """
234
263
  return self.all(session)
235
264
 
236
- @staticmethod
237
- def _is_model_accepted(model, parent: type[BaseModel] = BaseModel):
238
- """
239
- Checks if the model is an instance of BaseModel or its child.
240
- Raises:
241
- ValueError: If the model is not an instance of BaseModel or its child.
242
- """
243
- if not issubclass(model, parent):
244
- raise ValueError(
245
- f"Provided class_={model} is not a inherited from {parent}"
246
- )
247
-
248
265
  def with_relationships(self, selected: Iterable[str] | None = None) -> Self:
249
- """
250
- Adds relationships to the query.
266
+ """Adds relationships to the query.
251
267
 
252
268
  Args:
253
269
  selected (set[str]): A set of relationship names to include.
@@ -266,3 +282,30 @@ class BaseSelector: # pylint: disable=too-many-ancestors
266
282
  }
267
283
  self._statement = self._statement.options(*relationships)
268
284
  return self
285
+
286
+ @staticmethod
287
+ def _is_model_accepted(model, parent: type[BaseModel] = BaseModel):
288
+ """Checks if the model is an instance of BaseModel or its child.
289
+
290
+ Raises:
291
+ ValueError: If the model is not an instance of BaseModel or its child.
292
+ """
293
+ if not issubclass(model, parent):
294
+ raise ValueError(f"Provided model={model} is not a inherited from {parent}")
295
+
296
+ def _get_column(self, key: str | InstrumentedAttribute) -> InstrumentedAttribute:
297
+ """Get the column from the model.
298
+
299
+ Args:
300
+ key (str | InstrumentedAttribute): The key of the column to filter by.
301
+
302
+ Raises:
303
+ AttributeError: If the model has no attribute with the given key.
304
+
305
+ Returns:
306
+ InstrumentedAttribute: The SQLAlchemy column to filter by.
307
+ """
308
+ column = getattr(self.model, key, None) if isinstance(key, str) else key
309
+ if column is None:
310
+ raise AttributeError(f"Model {self.model} has no attribute {key}")
311
+ return column
@@ -87,7 +87,7 @@ class WordSelector(BaseSelector): # pylint: disable=too-many-ancestors
87
87
  Self: A query with the filter applied.
88
88
  """
89
89
  if hasattr(self.model, "name"):
90
- condition = self._generate_column_condition(self.model.name, name)
90
+ condition = self.get_like_condition(self.model.name, name)
91
91
  else:
92
92
  raise AttributeError(
93
93
  f"{self.model.__name__} does not have a 'name' attribute"
@@ -4,7 +4,7 @@ from io import open
4
4
 
5
5
  from setuptools import setup
6
6
 
7
- CURRENT_VERSION = "0.4.3"
7
+ CURRENT_VERSION = "0.4.5"
8
8
 
9
9
 
10
10
  def read(filename): # pylint: disable=C0116
File without changes
File without changes
File without changes
File without changes