Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement search equivalence of "jpg" and "jpeg" filetypes #649

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions docs/updates/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down
13 changes: 11 additions & 2 deletions tagstudio/src/core/library/alchemy/visitors.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
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

Expand All @@ -17,6 +17,13 @@
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__()
Expand Down Expand Up @@ -73,7 +80,9 @@ def visit_constraint(self, node: Constraint) -> 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_(
Expand Down
2 changes: 2 additions & 0 deletions tagstudio/src/core/media_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

logging.basicConfig(format="%(message)s", level=logging.INFO)

FILETYPE_EQUIVALENTS = [set(["jpg", "jpeg"])]


class MediaType(str, Enum):
"""Names of media types."""
Expand Down
Loading