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 testing support #88

Closed
wants to merge 10 commits into from
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ PySide6_Addons>=6.5.1.1,<=6.6.3.1
PySide6_Essentials>=6.5.1.1,<=6.6.3.1
typing_extensions>=3.10.0.0,<=4.11.0
ujson>=5.8.0,<=5.9.0
parametrized==0.9.0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
parametrized==0.9.0
parameterized==0.9.0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback! I have added a requirements-dev.txt as discussed in this MR with pytest.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this shouldnt be a production depedency, I'd suggest to create requirements-dev.txt or similar and put it there instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point. By the way, do you guys manually add those dependencies to the requirements.txt or can pip do that automtically like npm can?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's pip freeze which lists all currently installed packages, so you can do pip freeze > requirements.txt but it lists even the transitional dependencies which is suboptimal.

Ideally the project should use some advanced dep. management tool like Poetry or pdm, but seems like that isnt/wasnt a priority yet

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point,
I don't think there's currently a plan to switchover to a more robust dependency manager, not saying a switch shouldn't happen but I believe the energy is more focused on swapping the backend from a JSON file to a database.

Are there any recommendations aside from something like a requirements-dev.txt file to be a stopgap on this kind of thing?

Example

-r requirements.txt
parameterized==0.9.0

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd go with requirements-dev.txt and requirements-dev.txt without referencing each other, any dev will know how to deal with it. But I dont have strong opinion about it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you guys think about the latest changes? 😄

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd keep the original name requirements.txt instead of adding the -prod suffix there, as that's the most common name everyone looks for by default. Other than that it looks good to me, nice job.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thank you for the review 😄

41 changes: 41 additions & 0 deletions tagstudio/src/core/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
VERSION: str = '9.2.0' # Major.Minor.Patch
VERSION_BRANCH: str = 'Alpha' # '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']
44 changes: 21 additions & 23 deletions tagstudio/src/core/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
from enum import Enum
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 tagstudio.src.core.json_typing import JsonCollation, JsonEntry, JsonLibary, JsonTag
from tagstudio.src.core.constants import TS_FOLDER_NAME, BACKUP_FOLDER_NAME, COLLAGE_FOLDER_NAME, VERSION, TEXT_FIELDS
from tagstudio.src.core.utils.str import strip_punctuation
from tagstudio.src.core.utils.web import strip_web_protocol
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagstudio.src... import format breaks at runtime for vscode and when running from the terminal

Suggested change
from tagstudio.src.core.json_typing import JsonCollation, JsonEntry, JsonLibary, JsonTag
from tagstudio.src.core.constants import TS_FOLDER_NAME, BACKUP_FOLDER_NAME, COLLAGE_FOLDER_NAME, VERSION, TEXT_FIELDS
from tagstudio.src.core.utils.str import strip_punctuation
from tagstudio.src.core.utils.web import strip_web_protocol
from src.core.json_typing import JsonCollation, JsonEntry, JsonLibary, JsonTag
from src.core.constants import TS_FOLDER_NAME, BACKUP_FOLDER_NAME, COLLAGE_FOLDER_NAME, VERSION, TEXT_FIELDS
from src.core.utils.str import strip_punctuation
from src.core.utils.web import strip_web_protocol

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback! I have made the changes.


TYPE = ['file', 'meta', 'alt', 'mask']
# RESULT_TYPE = Enum('Result', ['ENTRY', 'COLLATION', 'TAG_GROUP'])
Expand Down Expand Up @@ -154,8 +154,6 @@ def add_tag(self, library:'Library', tag_id:int, field_id:int, field_index:int=N
self.fields[field_index][field_id] = sorted(tags, key=lambda t: library.get_tag(t).display_name(library))

# logging.info(f'Tags: {self.fields[field_index][field_id]}')



class Tag:
"""A Library Tag Object. Referenced by ID."""
Expand Down Expand Up @@ -546,8 +544,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 @@ -565,11 +563,11 @@ 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}')
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):
os.mkdir(full_ts_path)
Expand Down Expand Up @@ -606,13 +604,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'), 'r', encoding='utf-8') as f:
with open(os.path.normpath(f'{path}/{TS_FOLDER_NAME}/ts_library.json'), 'r', encoding='utf-8') as f:
json_dump: JsonLibary = ujson.load(f)
self.library_dir = str(path)
self.verify_ts_folders()
Expand Down Expand Up @@ -788,9 +786,9 @@ def open_library(self, path: str) -> int:
if return_code == 1:

if not os.path.exists(os.path.normpath(
f'{self.library_dir}/{ts_core.TS_FOLDER_NAME}')):
f'{self.library_dir}/{TS_FOLDER_NAME}')):
os.makedirs(os.path.normpath(
f'{self.library_dir}/{ts_core.TS_FOLDER_NAME}'))
f'{self.library_dir}/{TS_FOLDER_NAME}'))

self._map_filenames_to_entry_ids()

Expand Down Expand Up @@ -832,7 +830,7 @@ def to_json(self):
Used in saving the library to disk.
"""

file_to_save: JsonLibary = {"ts-version": ts_core.VERSION,
file_to_save: JsonLibary = {"ts-version": VERSION,
"ignored_extensions": [],
"tags": [],
"collations": [],
Expand Down Expand Up @@ -869,7 +867,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}'), 'w', encoding='utf-8') as outfile:
with open(os.path.normpath(f'{self.library_dir}/{TS_FOLDER_NAME}/{filename}'), 'w', encoding='utf-8') as outfile:
outfile.flush()
ujson.dump(self.to_json(), outfile, ensure_ascii=False, escape_forward_slashes=False)
# , indent=4 <-- How to prettyprint dump
Expand All @@ -886,7 +884,7 @@ def save_library_backup_to_disk(self) -> str:
filename = f'ts_library_backup_{datetime.datetime.utcnow().strftime("%F_%T").replace(":", "")}.json'

self.verify_ts_folders()
with open(os.path.normpath(f'{self.library_dir}/{ts_core.TS_FOLDER_NAME}/{ts_core.BACKUP_FOLDER_NAME}/{filename}'), 'w', encoding='utf-8') as outfile:
with open(os.path.normpath(f'{self.library_dir}/{TS_FOLDER_NAME}/{BACKUP_FOLDER_NAME}/{filename}'), 'w', encoding='utf-8') as outfile:
outfile.flush()
ujson.dump(self.to_json(), outfile, ensure_ascii=False, escape_forward_slashes=False)
end_time = time.time()
Expand Down Expand Up @@ -932,11 +930,11 @@ def refresh_dir(self):
# 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
if ('$RECYCLE.BIN' not in f and TS_FOLDER_NAME not in f
and 'tagstudio_thumbs' not in f and not os.path.isdir(f)):
if os.path.splitext(f)[1][1:].lower() not in self.ignored_extensions:
self.dir_file_count += 1
Expand Down Expand Up @@ -2034,7 +2032,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
46 changes: 2 additions & 44 deletions tagstudio/src/core/ts_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,50 +7,8 @@
import json
import os

from src.core.library import Entry, Library

VERSION: str = '9.2.0' # Major.Minor.Patch
VERSION_BRANCH: str = 'Alpha' # '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']

from tagstudio.src.core.constants import TEXT_FIELDS
from tagstudio.src.core.library import Entry, Library
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagstudio.src... import format breaks at runtime for vscode and when running from the terminal

Suggested change
from tagstudio.src.core.constants import TEXT_FIELDS
from tagstudio.src.core.library import Entry, Library
from src.core.constants import TEXT_FIELDS
from src.core.library import Entry, Library

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback! I have made the changes.


class TagStudioCore:
"""
Expand Down
15 changes: 9 additions & 6 deletions tagstudio/src/core/utils/str.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
# Licensed under the GPL-3.0 License.
# Created for TagStudio: https://github.com/CyanVoxel/TagStudio

def strip_punctuation(string: str) -> str:
def strip_punctuation(text: str) -> str:
"""Returns a given string stripped of all punctuation characters."""
return string.replace('(', '').replace(')', '').replace('[', '') \
.replace(']', '').replace('{', '').replace('}', '').replace("'", '') \
.replace('`', '').replace('’', '').replace('‘', '').replace('"', '') \
.replace('“', '').replace('”', '').replace('_', '').replace('-', '') \
.replace(' ', '').replace(' ', '')
punctuation = '{}[]()\'"`‘’“”-_  '
result = text

for p in punctuation:
result = result.replace(p, '')

return result

21 changes: 11 additions & 10 deletions tagstudio/src/qt/ts_qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,22 @@
from PySide6.QtWidgets import (QApplication, QWidget, QHBoxLayout, QPushButton, QLineEdit, QScrollArea, QFileDialog,
QSplashScreen, QMenu)
from humanfriendly import format_timespan

from src.core.library import ItemType
from src.core.ts_core import (PLAINTEXT_TYPES, TagStudioCore, TAG_COLORS, DATE_FIELDS, TEXT_FIELDS, BOX_FIELDS, ALL_FILE_TYPES,
from tagstudio.src.core.library import Collation, Entry, ItemType, Library, Tag
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line was previously reduced to only import ItemType as it is the only item used in ts_qt.py

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback! I have made the changes.

from tagstudio.src.core.palette import ColorType, get_tag_color
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line was removed in a previous commit and is no longer used in ts_qt.py

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback! I have made the changes.

from tagstudio.src.core.ts_core import TagStudioCore
from tagstudio.src.core.constants import (PLAINTEXT_TYPES, TAG_COLORS, DATE_FIELDS, TEXT_FIELDS, BOX_FIELDS, ALL_FILE_TYPES,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagstudio.src... import format breaks at runtime for vscode and when running from the terminal

Suggested change
from tagstudio.src.core.library import Collation, Entry, ItemType, Library, Tag
from tagstudio.src.core.palette import ColorType, get_tag_color
from tagstudio.src.core.ts_core import TagStudioCore
from tagstudio.src.core.constants import (PLAINTEXT_TYPES, TAG_COLORS, DATE_FIELDS, TEXT_FIELDS, BOX_FIELDS, ALL_FILE_TYPES,
from src.core.library import Collation, Entry, ItemType, Library, Tag
from src.core.palette import ColorType, get_tag_color
from src.core.ts_core import TagStudioCore
from src.core.constants import (PLAINTEXT_TYPES, TAG_COLORS, DATE_FIELDS, TEXT_FIELDS, BOX_FIELDS, ALL_FILE_TYPES,

SHORTCUT_TYPES, PROGRAM_TYPES, ARCHIVE_TYPES, PRESENTATION_TYPES,
SPREADSHEET_TYPES, DOC_TYPES, AUDIO_TYPES, VIDEO_TYPES, IMAGE_TYPES,
LIBRARY_FILENAME, COLLAGE_FOLDER_NAME, BACKUP_FOLDER_NAME, TS_FOLDER_NAME,
VERSION_BRANCH, VERSION)
from src.core.utils.web import strip_web_protocol
from src.qt.flowlayout import FlowLayout
from src.qt.main_window import Ui_MainWindow
from src.qt.helpers import FunctionIterator, CustomRunnable
from src.qt.widgets import CollageIconRenderer, ThumbRenderer, PanelModal, ProgressWidget, PreviewPanel, ItemThumb
from src.qt.modals import (BuildTagPanel, TagDatabasePanel, FileExtensionModal, FixUnlinkedEntriesModal,
from tagstudio.src.core.utils.web import strip_web_protocol
from tagstudio.src.qt.flowlayout import FlowLayout
from tagstudio.src.qt.main_window import Ui_MainWindow
from tagstudio.src.qt.helpers import FunctionIterator, CustomRunnable
from tagstudio.src.qt.widgets import CollageIconRenderer, ThumbRenderer, PanelModal, ProgressWidget, PreviewPanel, ItemThumb
from tagstudio.src.qt.modals import (BuildTagPanel, TagDatabasePanel, FileExtensionModal, FixUnlinkedEntriesModal,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagstudio.src... import format breaks at runtime for vscode and when running from the terminal

Suggested change
from tagstudio.src.core.utils.web import strip_web_protocol
from tagstudio.src.qt.flowlayout import FlowLayout
from tagstudio.src.qt.main_window import Ui_MainWindow
from tagstudio.src.qt.helpers import FunctionIterator, CustomRunnable
from tagstudio.src.qt.widgets import CollageIconRenderer, ThumbRenderer, PanelModal, ProgressWidget, PreviewPanel, ItemThumb
from tagstudio.src.qt.modals import (BuildTagPanel, TagDatabasePanel, FileExtensionModal, FixUnlinkedEntriesModal,
from src.core.utils.web import strip_web_protocol
from src.qt.flowlayout import FlowLayout
from src.qt.main_window import Ui_MainWindow
from src.qt.helpers import FunctionIterator, CustomRunnable
from src.qt.widgets import CollageIconRenderer, ThumbRenderer, PanelModal, ProgressWidget, PreviewPanel, ItemThumb
from src.qt.modals import (BuildTagPanel, TagDatabasePanel, FileExtensionModal, FixUnlinkedEntriesModal,

FixDupeFilesModal, FoldersToTagsModal)
import src.qt.resources_rc
import tagstudio.src.qt.resources_rc
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagstudio.src... import format breaks at runtime for vscode and when running from the terminal

Suggested change
import tagstudio.src.qt.resources_rc
import src.qt.resources_rc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback! I have made the changes.


# SIGQUIT is not defined on Windows
if sys.platform == "win32":
Expand Down
9 changes: 9 additions & 0 deletions tagstudio/tests/main.py
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm having luck getting python.exe -m unittest discover tagstudio.tests -t "tagstudio" to run from the <local_repo> directory but this file is throwing a fit working between all the different use cases.
Something like unittest.TestSuite() or unittest load test protocol might be more appropriate for the longer term and avoid needing to change the import format in the src library.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added pytest instead of unittest and I found that running python -m pytest tests/ from the tagstudio folder works. Does not seem to work any other way though.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import unittest

if __name__ == '__main__':
"""Runs every test."""
test_loader = unittest.TestLoader()
test_suite = test_loader.discover(start_dir='src', pattern='test_*.py')

runner = unittest.TextTestRunner()
result = runner.run(test_suite)
File renamed without changes.
Empty file.
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from src.core.library import Tag
import unittest

from tagstudio.src.core.library import Tag
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagstudio.src... import format breaks at runtime for vscode and when running from the terminal

Suggested change
from tagstudio.src.core.library import Tag
from src.core.library import Tag

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback! I have made the changes.


class TestTags:

class TestTags(unittest.TestCase):
def test_construction(self):
tag = Tag(id=1, name='Tag Name', shorthand='TN', aliases=[
'First A', 'Second A'], subtags_ids=[2, 3, 4], color='')
assert (tag)
assert tag

def test_empty_construction(self):
tag = Tag(id=1, name='', shorthand='', aliases=[], subtags_ids=[], color='')
assert (tag)
assert tag
Empty file.
16 changes: 16 additions & 0 deletions tagstudio/tests/src/utils/test_str.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import unittest

from parameterized import parameterized

from tagstudio.src.core.utils.str import strip_punctuation
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tagstudio.src... import format breaks at runtime for vscode and when running from the terminal

Suggested change
from tagstudio.src.core.utils.str import strip_punctuation
from src.core.utils.str import strip_punctuation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the feedback! I have made the changes.



class StrTest(unittest.TestCase):
@parameterized.expand([
('{[(parenthesis)]}', 'parenthesis'),
('‘“`"\'quotes\'"`”’', 'quotes'),
('_-  spacers', 'spacers'),
('{}[]()\'"`‘’“”-  ', '')
])
def test_strip_punctuation(self, text, expected_output):
self.assertEqual(strip_punctuation(text), expected_output)