-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
1,653 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
name: Publish package | ||
on: | ||
release: | ||
types: ["created"] | ||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Setup Poetry | ||
uses: abatilo/actions-poetry@v3 | ||
with: | ||
poetry-version: 1.8.2 | ||
- name: Set up Python | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: 3.11 | ||
cache: poetry | ||
- name: Install plugin | ||
run: poetry self add "poetry-dynamic-versioning[plugin]" | ||
- name: Set PyPI token | ||
env: | ||
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} | ||
run: poetry config pypi-token.pypi $PYPI_TOKEN | ||
- name: Build and publish | ||
run: poetry publish --build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
name: Test | ||
on: ["pull_request", "push"] | ||
jobs: | ||
test: | ||
runs-on: ubuntu-latest | ||
strategy: | ||
matrix: | ||
python-version: ["3.10", 3.11] | ||
poetry-version: [1.8.2] | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- name: Setup Poetry | ||
uses: abatilo/actions-poetry@v3 | ||
with: | ||
poetry-version: ${{ matrix.poetry-version }} | ||
- uses: actions/setup-python@v5 | ||
with: | ||
python-version: ${{ matrix.python-version }} | ||
cache: poetry | ||
- name: Install Python dependencies | ||
run: poetry install | ||
- name: Run tests | ||
run: poetry run pytest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
repos: | ||
- repo: https://github.com/pre-commit/pre-commit-hooks | ||
rev: v4.5.0 | ||
hooks: | ||
- id: check-added-large-files | ||
- id: check-toml | ||
- id: check-yaml | ||
args: | ||
- --unsafe | ||
- id: end-of-file-fixer | ||
- id: trailing-whitespace | ||
|
||
- repo: https://github.com/python-poetry/poetry | ||
rev: 1.8.0 | ||
hooks: | ||
- id: poetry-check | ||
|
||
- repo: https://github.com/andrei-shabanski/poetry-plugin-sort | ||
rev: v0.2.1 | ||
hooks: | ||
- id: poetry-sort | ||
|
||
- repo: https://github.com/asottile/pyupgrade | ||
rev: v3.15.2 | ||
hooks: | ||
- id: pyupgrade | ||
args: | ||
- --py310-plus | ||
|
||
- repo: https://github.com/charliermarsh/ruff-pre-commit | ||
rev: v0.3.4 | ||
hooks: | ||
- id: ruff | ||
args: | ||
- --fix | ||
- id: ruff-format | ||
|
||
- repo: https://github.com/pre-commit/mirrors-mypy | ||
rev: v1.9.0 | ||
hooks: | ||
- id: mypy | ||
additional_dependencies: | ||
- types-all |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,164 @@ | ||
# sqlmodel-filters | ||
# sqlmodel-filters | ||
|
||
A Lucene query like filter for [SQLModel](https://github.com/tiangolo/sqlmodel). | ||
|
||
> [!NOTE] | ||
> This is an alpha level library. Everything is subject to change & there are some known limitations. | ||
## Installation | ||
|
||
```bash | ||
pip install sqlmodel_filters | ||
``` | ||
|
||
## How to Use | ||
|
||
Let's say we have the following model & records: | ||
|
||
```py | ||
import datetime | ||
from functools import partial | ||
from typing import Optional | ||
|
||
from sqlmodel import Field, SQLModel | ||
|
||
|
||
class Hero(SQLModel, table=True): | ||
id: Optional[int] = Field(default=None, primary_key=True) | ||
name: str | ||
secret_name: str | ||
age: Optional[int] = None | ||
created_at: datetime.datetime = Field( | ||
default_factory=partial(datetime.datetime.now, datetime.UTC) | ||
) | ||
|
||
hero_1 = Hero(name="Deadpond", secret_name="Dive Wilson") | ||
hero_2 = Hero(name="Spider-Boy", secret_name="Pedro Parqueador") | ||
hero_3 = Hero(name="Rusty-Man", secret_name="Tommy Sharp", age=48) | ||
|
||
|
||
engine = create_engine("sqlite://") | ||
|
||
|
||
SQLModel.metadata.create_all(engine) | ||
|
||
with Session(engine) as session: | ||
session.add(hero_1) | ||
session.add(hero_2) | ||
session.add(hero_3) | ||
session.commit() | ||
``` | ||
|
||
And let's try querying with this library. | ||
|
||
```py | ||
# this library relies on luqum (https://github.com/jurismarches/luqum) for parsing Lucene query | ||
from luqum import parse | ||
from sqlmodel import Session | ||
|
||
from sqlmodel_filters import Builder | ||
|
||
# parse a Lucene query | ||
parsed = parse('name:Spider') | ||
# build SELECT statement for Hero based on the parsed query | ||
builder = Builder(Hero) | ||
statement = builder(parsed) | ||
|
||
# the following is a compiled SQL query | ||
statement.compile(compile_kwargs={"literal_binds": True}) | ||
>>> SELECT hero.id, hero.name, hero.secret_name, hero.age, hero.created_at | ||
>>> FROM hero | ||
>>> WHERE hero.name = '%Spider%' | ||
|
||
# you can use the statement like this | ||
heros = session.exec(statement).all() | ||
assert len(heros) == 1 | ||
assert heros[0].name == "Spider-Boy" | ||
``` | ||
|
||
Note that a value is automatically casted based on a field definition. | ||
|
||
```py | ||
# age: Optional[int] | ||
"age:48" | ||
>>> WHERE hero.age = 48 | ||
|
||
# created_at: datetime.datetime | ||
"created_at:2020-01-01" | ||
>>> WHERE hero.created_at = '2020-01-01 00:00:00' | ||
``` | ||
|
||
### `Word` (`Term`) | ||
|
||
Double quote a value if you want to use the equal operator. | ||
|
||
```py | ||
'name:"Spider-Boy"' | ||
>>> WHERE hero.name = 'Spider-Boy' | ||
``` | ||
|
||
The `LIKE` operator is used when you don't double quote a value. | ||
|
||
```py | ||
"name:Spider" | ||
>>> WHERE hero.name LIKE '%Spider%' | ||
``` | ||
|
||
Use `?` (a single character wildcard) or `*` (a multiple character wildcard) to control a LIKE operator pattern. | ||
|
||
```py | ||
"name:Deadpond?" | ||
>>> WHERE hero.name LIKE 'Deadpond_' | ||
|
||
"name:o*" | ||
>>> WHERE hero.name LIKE 'o%' | ||
``` | ||
|
||
### `FROM` & `TO` | ||
|
||
```py | ||
"age:>=40" | ||
>>> WHERE hero.age >= 40 | ||
|
||
"age:>40" | ||
>>> WHERE hero.age > 40 | ||
``` | ||
|
||
```py | ||
"age:<=40" | ||
>>> WHERE hero.age <= 40 | ||
|
||
"age:<40" | ||
>>> WHERE hero.age < 40 | ||
``` | ||
|
||
### `RANGE` | ||
|
||
```py | ||
"age:{48 TO 60}" | ||
>>> WHERE hero.age < 60 AND hero.age > 48 | ||
|
||
"age:[48 TO 60]" | ||
>>> WHERE hero.age <= 60 AND hero.age >= 48 | ||
``` | ||
|
||
## `AND`, `OR`, `NOT` and `GROUP` (Grouping) | ||
|
||
```py | ||
"name:Rusty AND age:48" | ||
>>> WHERE hero.name LIKE '%Rusty%' AND hero.age = 48 | ||
|
||
"name:Rusty OR age:47" | ||
>>> WHERE hero.name LIKE '%Rusty%' OR hero.age = 47 | ||
|
||
"name:Rusty NOT age:47" | ||
>>> WHERE hero.name LIKE '%Rusty%' AND hero.age != 47 | ||
|
||
"(name:Spider OR age:48) AND name:Rusty" | ||
>>> WHERE (hero.name LIKE '%Spider%' OR hero.age = 48) AND hero.name LIKE '%Rusty%' | ||
``` | ||
|
||
## Known Limitations / Todos | ||
|
||
- Relationship join is not supported | ||
- Filed Grouping is not supported |
Oops, something went wrong.