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

Add pytest support #142

Merged
merged 8 commits into from
May 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,12 @@ _Skip these steps if launching from the .sh script on Linux/macOS._
- Linux/macOS: `source .venv/bin/activate`

3. Install the required packages:
`pip install -r requirements.txt`

- required to run the app: `pip install -r requirements.txt`
- required to develop: `pip install -r requirements-dev.txt`


To run all the tests use `python -m pytest tests/` from the `tagstudio` folder.

_Learn more about setting up a virtual environment [here](https://docs.python.org/3/tutorial/venv.html)._

Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ruff==0.4.2
pre-commit==3.7.0
pytest==8.2.0
Pyinstaller==6.6.0
mypy==1.10.0
136 changes: 136 additions & 0 deletions tagstudio/src/core/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
VERSION: str = "9.2.1" # Major.Minor.Patch
VERSION_BRANCH: str = "Pre-Release" # 'Alpha', 'Beta', or '' for Full Release

# The folder & file names where TagStudio keeps its data relative to a library.
TS_FOLDER_NAME: str = ".TagStudio"
BACKUP_FOLDER_NAME: str = "backups"
COLLAGE_FOLDER_NAME: str = "collages"
LIBRARY_FILENAME: str = "ts_library.json"

# TODO: Turn this whitelist into a user-configurable blacklist.
IMAGE_TYPES: list[str] = [
"png",
"jpg",
"jpeg",
"jpg_large",
"jpeg_large",
"jfif",
"gif",
"tif",
"tiff",
"heic",
"heif",
"webp",
"bmp",
"svg",
"avif",
"apng",
"jp2",
"j2k",
"jpg2",
]
VIDEO_TYPES: list[str] = [
"mp4",
"webm",
"mov",
"hevc",
"mkv",
"avi",
"wmv",
"flv",
"gifv",
"m4p",
"m4v",
"3gp",
]
AUDIO_TYPES: list[str] = [
"mp3",
"mp4",
"mpeg4",
"m4a",
"aac",
"wav",
"flac",
"alac",
"wma",
"ogg",
"aiff",
]
DOC_TYPES: list[str] = ["txt", "rtf", "md", "doc", "docx", "pdf", "tex", "odt", "pages"]
PLAINTEXT_TYPES: list[str] = [
"txt",
"md",
"css",
"html",
"xml",
"json",
"js",
"ts",
"ini",
"htm",
"csv",
"php",
"sh",
"bat",
]
SPREADSHEET_TYPES: list[str] = ["csv", "xls", "xlsx", "numbers", "ods"]
PRESENTATION_TYPES: list[str] = ["ppt", "pptx", "key", "odp"]
ARCHIVE_TYPES: list[str] = ["zip", "rar", "tar", "tar.gz", "tgz", "7z"]
PROGRAM_TYPES: list[str] = ["exe", "app"]
SHORTCUT_TYPES: list[str] = ["lnk", "desktop", "url"]

ALL_FILE_TYPES: list[str] = (
IMAGE_TYPES
+ VIDEO_TYPES
+ AUDIO_TYPES
+ DOC_TYPES
+ SPREADSHEET_TYPES
+ PRESENTATION_TYPES
+ ARCHIVE_TYPES
+ PROGRAM_TYPES
+ SHORTCUT_TYPES
)

BOX_FIELDS = ["tag_box", "text_box"]
TEXT_FIELDS = ["text_line", "text_box"]
DATE_FIELDS = ["datetime"]

TAG_COLORS = [
"",
"black",
"dark gray",
"gray",
"light gray",
"white",
"light pink",
"pink",
"red",
"red orange",
"orange",
"yellow orange",
"yellow",
"lime",
"light green",
"mint",
"green",
"teal",
"cyan",
"light blue",
"blue",
"blue violet",
"violet",
"purple",
"lavender",
"berry",
"magenta",
"salmon",
"auburn",
"dark brown",
"brown",
"light brown",
"blonde",
"peach",
"warm gray",
"cool gray",
"olive",
]
48 changes: 24 additions & 24 deletions tagstudio/src/core/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,15 @@
import ujson

from src.core.json_typing import JsonCollation, JsonEntry, JsonLibary, JsonTag
from src.core import ts_core
from src.core.utils.str import strip_punctuation
from src.core.utils.web import strip_web_protocol
from src.core.constants import (
BACKUP_FOLDER_NAME,
COLLAGE_FOLDER_NAME,
TEXT_FIELDS,
TS_FOLDER_NAME,
VERSION,
)

TYPE = ["file", "meta", "alt", "mask"]

Expand Down Expand Up @@ -444,8 +450,8 @@ def create_library(self, path) -> int:
path = os.path.normpath(path).rstrip("\\")

# If '.TagStudio' is included in the path, trim the path up to it.
if ts_core.TS_FOLDER_NAME in path:
path = path.split(ts_core.TS_FOLDER_NAME)[0]
if TS_FOLDER_NAME in path:
path = path.split(TS_FOLDER_NAME)[0]

try:
self.clear_internal_vars()
Expand All @@ -462,12 +468,12 @@ def create_library(self, path) -> int:
def verify_ts_folders(self) -> None:
"""Verifies/creates folders required by TagStudio."""

full_ts_path = os.path.normpath(f"{self.library_dir}/{ts_core.TS_FOLDER_NAME}")
full_ts_path = os.path.normpath(f"{self.library_dir}/{TS_FOLDER_NAME}")
full_backup_path = os.path.normpath(
f"{self.library_dir}/{ts_core.TS_FOLDER_NAME}/{ts_core.BACKUP_FOLDER_NAME}"
f"{self.library_dir}/{TS_FOLDER_NAME}/{BACKUP_FOLDER_NAME}"
)
full_collage_path = os.path.normpath(
f"{self.library_dir}/{ts_core.TS_FOLDER_NAME}/{ts_core.COLLAGE_FOLDER_NAME}"
f"{self.library_dir}/{TS_FOLDER_NAME}/{COLLAGE_FOLDER_NAME}"
)

if not os.path.isdir(full_ts_path):
Expand Down Expand Up @@ -505,17 +511,13 @@ def open_library(self, path: str) -> int:
path = os.path.normpath(path).rstrip("\\")

# If '.TagStudio' is included in the path, trim the path up to it.
if ts_core.TS_FOLDER_NAME in path:
path = path.split(ts_core.TS_FOLDER_NAME)[0]
if TS_FOLDER_NAME in path:
path = path.split(TS_FOLDER_NAME)[0]

if os.path.exists(
os.path.normpath(f"{path}/{ts_core.TS_FOLDER_NAME}/ts_library.json")
):
if os.path.exists(os.path.normpath(f"{path}/{TS_FOLDER_NAME}/ts_library.json")):
try:
with open(
os.path.normpath(
f"{path}/{ts_core.TS_FOLDER_NAME}/ts_library.json"
),
os.path.normpath(f"{path}/{TS_FOLDER_NAME}/ts_library.json"),
"r",
encoding="utf-8",
) as file:
Expand Down Expand Up @@ -724,11 +726,9 @@ def open_library(self, path: str) -> int:
# If the Library is loaded, continue other processes.
if return_code == 1:
if not os.path.exists(
os.path.normpath(f"{self.library_dir}/{ts_core.TS_FOLDER_NAME}")
os.path.normpath(f"{self.library_dir}/{TS_FOLDER_NAME}")
):
os.makedirs(
os.path.normpath(f"{self.library_dir}/{ts_core.TS_FOLDER_NAME}")
)
os.makedirs(os.path.normpath(f"{self.library_dir}/{TS_FOLDER_NAME}"))

self._map_filenames_to_entry_ids()

Expand Down Expand Up @@ -775,7 +775,7 @@ def to_json(self):
"""

file_to_save: JsonLibary = {
"ts-version": ts_core.VERSION,
"ts-version": VERSION,
"ignored_extensions": [],
"tags": [],
"collations": [],
Expand Down Expand Up @@ -813,7 +813,7 @@ def save_library_to_disk(self):
self.verify_ts_folders()

with open(
os.path.normpath(f"{self.library_dir}/{ts_core.TS_FOLDER_NAME}/{filename}"),
os.path.normpath(f"{self.library_dir}/{TS_FOLDER_NAME}/{filename}"),
"w",
encoding="utf-8",
) as outfile:
Expand Down Expand Up @@ -842,7 +842,7 @@ def save_library_backup_to_disk(self) -> str:
self.verify_ts_folders()
with open(
os.path.normpath(
f"{self.library_dir}/{ts_core.TS_FOLDER_NAME}/{ts_core.BACKUP_FOLDER_NAME}/{filename}"
f"{self.library_dir}/{TS_FOLDER_NAME}/{BACKUP_FOLDER_NAME}/{filename}"
),
"w",
encoding="utf-8",
Expand Down Expand Up @@ -899,13 +899,13 @@ def refresh_dir(self) -> Generator:
# Scans the directory for files, keeping track of:
# - Total file count
# - Files without library entries
# for type in ts_core.TYPES:
# for type in TYPES:
start_time = time.time()
for f in glob.glob(self.library_dir + "/**/*", recursive=True):
# p = Path(os.path.normpath(f))
if (
"$RECYCLE.BIN" not in f
and ts_core.TS_FOLDER_NAME not in f
and TS_FOLDER_NAME not in f
and "tagstudio_thumbs" not in f
and not os.path.isdir(f)
):
Expand Down Expand Up @@ -2121,7 +2121,7 @@ def add_field_to_entry(self, entry_id: int, field_id: int) -> None:
# entry = self.entries[entry_index]
entry = self.get_entry(entry_id)
field_type = self.get_field_obj(field_id)["type"]
if field_type in ts_core.TEXT_FIELDS:
if field_type in TEXT_FIELDS:
entry.fields.append({int(field_id): ""})
elif field_type == "tag_box":
entry.fields.append({int(field_id): []})
Expand Down