diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 80de32e0..11a523d9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -77,6 +77,9 @@ jobs: echo "\n\nStarting CLI..." echo "gtimeout 10 ${{ steps.build-exe.outputs.out-filepath }}/Contents/MacOS/${{ steps.build-exe.outputs.out-filename }} --user-interface=cli" | bash || true + zip -r9 ${{ steps.build-exe.outputs.zip-filepath }} ${{ steps.build-exe.outputs.out-filepath }} || true + rm -rf ${{ steps.build-exe.outputs.out-filepath }} + - name: Test executable [Windows] if: runner.os == 'Windows' shell: bash @@ -163,9 +166,19 @@ jobs: - name: Upload uses: "softprops/action-gh-release@v2" + id: release with: tag_name: ${{github.ref_name}} make_latest: ${{github.event_name == 'push'}} generate_release_notes: true files: | build/*/exe/TiLiA-v* + + - name: Check output + run: | + assets=${{ fromJSON(steps.release.outputs.assets) }} + echo asset count: ${#assets[@]} + if [ "${#assets[@]}" != 4 ]; then + echo "::error::Incorrect number of assets in release. Potential errors in build." + exit 1 + fi diff --git a/scripts/deploy.py b/scripts/deploy.py index 10b0461d..a04a7752 100644 --- a/scripts/deploy.py +++ b/scripts/deploy.py @@ -166,6 +166,23 @@ def _create_lib() -> Path: return lib / tilia +def _get_implicit_imports(): + from tilia.utils import get_sibling_packages + + tls = [ + tl + ".timeline" + for tl in get_sibling_packages( + "tilia.timelines.base.timeline", + (Path(__file__).parent.parent / "tilia/timelines/base/timeline").as_posix(), + ) + ] + tluis = get_sibling_packages( + "tilia.ui.timelines.base.timeline", + (Path(__file__).parent.parent / "tilia/ui/timelines/base/timeline").as_posix(), + ) + return tls + tluis + + def _update_yml(): if not Path(pkg_cfg).exists(): return @@ -191,6 +208,7 @@ def _update_yml(): }, {"include-metadata": ["TiLiA"]}, ], + "implicit-imports": [{"depends": _get_implicit_imports()}], } ) @@ -255,16 +273,16 @@ def build(): _build_exe() if os.environ.get("GITHUB_OUTPUT"): if "mac" in build_os: - os.rename( - outdir / "exe" / "tilia.app", - outdir / "exe" / (out_filename + ".app"), - ) - out_filepath = outdir / "exe" / (out_filename + ".app") + out_filepath = outdir / "exe" / "tilia.app" else: out_filepath = outdir / "exe" / out_filename with open(os.environ["GITHUB_OUTPUT"], "a") as f: f.write(f"out-filepath={out_filepath.as_posix()}\n") f.write(f"out-filename={out_filename}\n") + if "mac" in build_os: + f.write( + f"zip-filepath={outdir.as_posix()}/exe/{out_filename}.zip\n" + ) os.chdir(old_dir) dotenv.set_key(".tilia.env", "ENVIRONMENT", old_env_var) except Exception as e: diff --git a/tilia/timelines/base/timeline.py b/tilia/timelines/base/timeline.py index 2d4b65a8..6a221d39 100644 --- a/tilia/timelines/base/timeline.py +++ b/tilia/timelines/base/timeline.py @@ -3,10 +3,8 @@ import functools import bisect import importlib -import os from abc import ABC from enum import Enum, auto -from pathlib import Path from typing import Any, Callable, TYPE_CHECKING, TypeVar, Generic, Set from tilia.timelines import serialize @@ -16,6 +14,7 @@ SetTimelineDataError, GetTimelineDataError, ) +from tilia.utils import get_sibling_packages from .validators import ( validate_string, validate_read_only, @@ -137,15 +136,10 @@ def subclasses(cls): @classmethod def ensure_subclasses_are_available(cls): - timelines_dir = Path(os.path.dirname(__file__)).parent - packages = [ - "tilia.timelines." + d.name + ".timeline" - for d in timelines_dir.iterdir() - if d.is_dir() and d.name not in ["base", "__pycache__", "collection"] - ] + packages = get_sibling_packages(__name__, __file__) for pkg in packages: try: - importlib.import_module(pkg) + importlib.import_module(pkg + ".timeline") except ModuleNotFoundError: print(f"Could not find timeline class in {pkg}.") diff --git a/tilia/ui/timelines/base/timeline.py b/tilia/ui/timelines/base/timeline.py index 8d011197..e1307474 100644 --- a/tilia/ui/timelines/base/timeline.py +++ b/tilia/ui/timelines/base/timeline.py @@ -1,9 +1,7 @@ from __future__ import annotations import functools import importlib -import os from abc import ABC -from pathlib import Path from typing import ( Any, TYPE_CHECKING, @@ -30,6 +28,7 @@ get_copy_data_from_element, ) from tilia.ui import commands +from tilia.utils import get_sibling_packages from ..view import TimelineView from ...coords import time_x_converter from ...windows import WindowKind @@ -118,12 +117,7 @@ def subclasses(cls): @classmethod def ensure_subclasses_are_available(cls): - timelines_dir = Path(os.path.dirname(__file__)).parent - packages = [ - "tilia.ui.timelines." + d.name - for d in timelines_dir.iterdir() - if d.is_dir() and d.name not in ["base", "__pycache__"] - ] + packages = get_sibling_packages(__name__, __file__) for pkg in packages: importlib.import_module(pkg) diff --git a/tilia/utils.py b/tilia/utils.py index 5b0766d1..26011c94 100644 --- a/tilia/utils.py +++ b/tilia/utils.py @@ -2,6 +2,7 @@ import subprocess import sys from pathlib import Path +from pkgutil import iter_modules from typing import Any @@ -9,6 +10,16 @@ def get_tilia_class_string(self: Any) -> str: return self.__class__.__name__ + "-" + str(id(self)) +def get_sibling_packages(m_name: str, m_file: str): + parent_path = Path(os.path.dirname(m_file)).parent + parent_package = ".".join(m_name.split(".")[:-2]) + return [ + ".".join([parent_package, d.name]) + for d in iter_modules([parent_path]) + if d.ispkg and d.name not in ["base", "__pycache__"] + ] + + def open_with_os(path: Path) -> None: if not os.path.exists(path): raise FileNotFoundError(f"File not found: {path}")