mirror of
https://github.com/TagStudioDev/TagStudio.git
synced 2026-01-29 06:10:51 +00:00
feat: implement search equivalence of "jpg" and "jpeg" filetypes (#649)
* feat: implement search equivalence of "jpg" and "jpeg" filetypes in an extensible manner * docs: update completion for search features on roadmap * fix: move FILETYPE_EQUIVALENTS to media_types.py
This commit is contained in:
@@ -86,13 +86,13 @@ Features are broken up into the following priority levels, with nested prioritie
|
||||
- [ ] GPS Location [LOW]
|
||||
- [ ] Custom field names [HIGH] [#18](https://github.com/TagStudioDev/TagStudio/issues/18)
|
||||
- [ ] Search engine [HIGH] [#325](https://github.com/TagStudioDev/TagStudio/issues/325)
|
||||
- [ ] Boolean operators [HIGH] [#225](https://github.com/TagStudioDev/TagStudio/issues/225), [#314](https://github.com/TagStudioDev/TagStudio/issues/314)
|
||||
- [x] Boolean operators [HIGH] [#225](https://github.com/TagStudioDev/TagStudio/issues/225), [#314](https://github.com/TagStudioDev/TagStudio/issues/314)
|
||||
- [ ] Tag objects + autocomplete [HIGH] [#476 (Autocomplete)](https://github.com/TagStudioDev/TagStudio/issues/476)
|
||||
- [ ] Filename search [HIGH]
|
||||
- [ ] Filetype search [HIGH]
|
||||
- [ ] Search by extension (e.g. ".jpg", ".png") [HIGH]
|
||||
- [ ] Optional consolidation of extension synonyms (i.e. ".jpg" can equal ".jpeg") [LOW]
|
||||
- [ ] Search by media type (e.g. "image", "video", "document") [MEDIUM]
|
||||
- [x] Filename search [HIGH]
|
||||
- [x] Filetype search [HIGH]
|
||||
- [x] Search by extension (e.g. ".jpg", ".png") [HIGH]
|
||||
- [x] Optional consolidation of extension synonyms (i.e. ".jpg" can equal ".jpeg") [LOW]
|
||||
- [x] Search by media type (e.g. "image", "video", "document") [MEDIUM]
|
||||
- [ ] Field content search [HIGH] [#272](https://github.com/TagStudioDev/TagStudio/issues/272)
|
||||
- [ ] HAS operator for composition tags [HIGH]
|
||||
- [ ] OCR search [LOW]
|
||||
@@ -172,12 +172,12 @@ These version milestones are rough estimations for when the previous core featur
|
||||
- [ ] [Tag Categories](../library/tag_categories.md) [HIGH]
|
||||
- [ ] Property available for tags that allow the tag and any inheriting from it to be displayed separately in the preview panel under a title [HIGH]
|
||||
- [ ] Search engine [HIGH]
|
||||
- [ ] Boolean operators [HIGH]
|
||||
- [x] Boolean operators [HIGH]
|
||||
- [ ] Tag objects + autocomplete [HIGH]
|
||||
- [x] Filename search [HIGH]
|
||||
- [x] Filetype search [HIGH]
|
||||
- [x] Search by extension (e.g. ".jpg", ".png") [HIGH]
|
||||
- [ ] Optional consolidation of extension synonyms (i.e. ".jpg" can equal ".jpeg") [LOW]
|
||||
- [x] Optional consolidation of extension synonyms (i.e. ".jpg" can equal ".jpeg") [LOW]
|
||||
- [x] Search by media type (e.g. "image", "video", "document") [MEDIUM]
|
||||
- [ ] Field content search [HIGH]
|
||||
- [ ] Sortable results [HIGH]
|
||||
|
||||
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
|
||||
from sqlalchemy import and_, distinct, func, or_, select
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.sql.expression import BinaryExpression, ColumnExpressionArgument
|
||||
from src.core.media_types import MediaCategories
|
||||
from src.core.media_types import FILETYPE_EQUIVALENTS, MediaCategories
|
||||
from src.core.query_lang import BaseVisitor
|
||||
from src.core.query_lang.ast import AST, ANDList, Constraint, ConstraintType, Not, ORList, Property
|
||||
|
||||
@@ -17,6 +17,13 @@ else:
|
||||
Library = None # don't import .library because of circular imports
|
||||
|
||||
|
||||
def get_filetype_equivalency_list(item: str) -> list[str] | set[str]:
|
||||
for s in FILETYPE_EQUIVALENTS:
|
||||
if item in s:
|
||||
return s
|
||||
return [item]
|
||||
|
||||
|
||||
class SQLBoolExpressionBuilder(BaseVisitor[ColumnExpressionArgument]):
|
||||
def __init__(self, lib: Library) -> None:
|
||||
super().__init__()
|
||||
@@ -73,7 +80,9 @@ class SQLBoolExpressionBuilder(BaseVisitor[ColumnExpressionArgument]):
|
||||
break
|
||||
return Entry.suffix.in_(map(lambda x: x.replace(".", ""), extensions))
|
||||
elif node.type == ConstraintType.FileType:
|
||||
return Entry.suffix.ilike(node.value)
|
||||
return or_(
|
||||
*[Entry.suffix.ilike(ft) for ft in get_filetype_equivalency_list(node.value)]
|
||||
)
|
||||
elif node.type == ConstraintType.Special: # noqa: SIM102 unnecessary once there is a second special constraint
|
||||
if node.value.lower() == "untagged":
|
||||
return ~Entry.id.in_(
|
||||
|
||||
@@ -10,6 +10,8 @@ from pathlib import Path
|
||||
|
||||
logging.basicConfig(format="%(message)s", level=logging.INFO)
|
||||
|
||||
FILETYPE_EQUIVALENTS = [set(["jpg", "jpeg"])]
|
||||
|
||||
|
||||
class MediaType(str, Enum):
|
||||
"""Names of media types."""
|
||||
|
||||
Reference in New Issue
Block a user