Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
run: pylint trackpack test
- name: Lint (ruff)
run: ruff check --output-format=github .
- name: Lint (pyrefly)
run: pyrefly check

formatting:
name: formatting
Expand Down
7 changes: 7 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ classifiers = [
"Topic :: Utilities"
]

[tool.pyrefly]
project-includes = [
"**/*.py*",
"**/*.ipynb",
]

[project.urls]
"Homepage" = "https://github.com/offa/trackpack"

Expand All @@ -26,6 +32,7 @@ trackpack = "trackpack.__main__:main"
[project.optional-dependencies]
dev = [
"pylint == 4.0.4",
"pyrefly==0.44.2",
"pytest == 9.0.2",
"ruff == 0.14.8"
]
Expand Down
10 changes: 5 additions & 5 deletions test/cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,27 @@


class TestCli(unittest.TestCase):
def test_prints_help_if_no_arguments_passed(self):
def test_prints_help_if_no_arguments_passed(self) -> None:
with self.assertRaises(SystemExit) as context:
cli.parse_args([])
self.assertEqual(0, context.exception.code)

def test_pack_command_default(self):
def test_pack_command_default(self) -> None:
args = cli.parse_args(["pack"])
self.assertEqual("pack", args.command)
self.assertFalse(args.pack_explicit_files)

def test_pack_command_with_explicit_file(self):
def test_pack_command_with_explicit_file(self) -> None:
args = cli.parse_args(["pack", "f0.wav", "f1.wav"])
self.assertEqual("pack", args.command)
self.assertEqual(["f0.wav", "f1.wav"], args.pack_explicit_files)

def test_pack_with_custom_archive_name(self):
def test_pack_with_custom_archive_name(self) -> None:
args = cli.parse_args(["pack", "--archive-name", "xyz"])
self.assertEqual("pack", args.command)
self.assertEqual("xyz", args.archive_name)

def test_pack_with_date(self):
def test_pack_with_date(self) -> None:
args = cli.parse_args(["pack", "--append-date"])
self.assertEqual("pack", args.command)
self.assertTrue(args.append_date)
10 changes: 5 additions & 5 deletions test/config_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,26 @@


class TestConfig(unittest.TestCase):
def test_default_config(self):
def test_default_config(self) -> None:
cfg = config.Config()
self.assertEqual("unnamed", cfg.name)
self.assertEqual("unnamed", cfg.archive_name)
self.assertEqual("Export", cfg.export_dir)
self.assertFalse(cfg.append_date)

def test_extension_is_stripped_from_archivename(self):
def test_extension_is_stripped_from_archivename(self) -> None:
cfg = config.Config()
cfg.archive_name = "stems.zip"
self.assertEqual("stems", cfg.archive_name)

@patch("trackpack.config.date", Mock(today=lambda: datetime.date(2020, 1, 1)))
def test_append_date_appends_date_to_archive_name(self):
def test_append_date_appends_date_to_archive_name(self) -> None:
cfg = config.Config()
cfg.archive_name = "xyz"
cfg.append_date = True
self.assertEqual("xyz-2020-01-01", cfg.archive_name)

def test_load_from_yaml(self):
def test_load_from_yaml(self) -> None:
cfg = config.Config()
cfg.load_from_yaml("name: project-1")
self.assertEqual("project-1", cfg.name)
Expand All @@ -58,7 +58,7 @@ def test_load_from_yaml(self):
self.assertTrue(cfg.append_date)

@patch("trackpack.config.date", Mock(today=lambda: datetime.date(2020, 1, 2)))
def test_load_from_cli_args(self):
def test_load_from_cli_args(self) -> None:
args = cli.parse_args(["pack", "--archive-name", "proj.zip", "--append-date"])
cfg = config.Config()
cfg.archive_name = "should override"
Expand Down
32 changes: 20 additions & 12 deletions test/trackpack_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

class TestTrackPack(unittest.TestCase):
@patch("os.walk")
def test_discover_audiofiles_returns_audio_files(self, walk_mock):
def test_discover_audiofiles_returns_audio_files(self, walk_mock) -> None:
walk_mock.return_value = _create_walk_files(
[
"proj stem2.wav",
Expand Down Expand Up @@ -52,7 +52,9 @@ def test_discover_audiofiles_returns_audio_files(self, walk_mock):
)

@patch("os.walk")
def test_discover_audiofiles_returns_only_related_audio_files(self, walk_mock):
def test_discover_audiofiles_returns_only_related_audio_files(
self, walk_mock
) -> None:
walk_mock.return_value = _create_walk_files(
[
"proj stem2.wav",
Expand All @@ -71,7 +73,9 @@ def test_discover_audiofiles_returns_only_related_audio_files(self, walk_mock):
)

@patch("os.walk")
def test_discover_audiofiles_master_track_matches_project_name(self, walk_mock):
def test_discover_audiofiles_master_track_matches_project_name(
self, walk_mock
) -> None:
walk_mock.return_value = _create_walk_files(
[
"example.wav",
Expand All @@ -86,7 +90,7 @@ def test_discover_audiofiles_master_track_matches_project_name(self, walk_mock):
self.assertEqual("example.wav", master)

@patch("os.walk")
def test_discover_audiofiles_fails_if_no_master(self, walk_mock):
def test_discover_audiofiles_fails_if_no_master(self, walk_mock) -> None:
walk_mock.return_value = _create_walk_files(
["proj stem1.wav", "proj stem2.wav"]
)
Expand All @@ -96,15 +100,17 @@ def test_discover_audiofiles_fails_if_no_master(self, walk_mock):
trackpacker.discover_audiofiles()

@patch("os.walk")
def test_discover_audiofiles_fails_if_no_stems(self, walk_mock):
def test_discover_audiofiles_fails_if_no_stems(self, walk_mock) -> None:
walk_mock.return_value = _create_walk_files(["proj.wav"])

with self.assertRaises(MissingFileException):
trackpacker = TrackPacker("proj", "/tmp/export")
trackpacker.discover_audiofiles()

@patch("os.walk")
def test_discover_audiofiles_returns_explicit_passed_audio_files(self, walk_mock):
def test_discover_audiofiles_returns_explicit_passed_audio_files(
self, walk_mock
) -> None:
walk_mock.return_value = _create_walk_files(
[
"proj stem2.wav",
Expand All @@ -128,7 +134,7 @@ def test_discover_audiofiles_returns_explicit_passed_audio_files(self, walk_mock
)

@patch("trackpack.trackpacker.ZipFile", autospec=True)
def test_pack_files_creates_archive_of_stems(self, zip_mock):
def test_pack_files_creates_archive_of_stems(self, zip_mock) -> None:
trackpacker = TrackPacker("projname", "/tmp/proj/Export")
trackpacker.pack_files(
"archivename",
Expand All @@ -143,7 +149,7 @@ def test_pack_files_creates_archive_of_stems(self, zip_mock):
)

@patch("trackpack.trackpacker.ZipFile", autospec=True)
def test_pack_files_removes_project_name_from_stems(self, zip_mock):
def test_pack_files_removes_project_name_from_stems(self, zip_mock) -> None:
trackpacker = TrackPacker("proj1", "/tmp/x")
trackpacker.pack_files(
"archive1", _files_in_dir("/tmp/x", ["proj1 a.wav", "b.wav", "proj1 c.wav"])
Expand All @@ -157,7 +163,7 @@ def test_pack_files_removes_project_name_from_stems(self, zip_mock):
)

@patch("trackpack.trackpacker.ZipFile", autospec=True)
def test_pack_files_replaces_blanks_in_names(self, zip_mock):
def test_pack_files_replaces_blanks_in_names(self, zip_mock) -> None:
trackpacker = TrackPacker("proj1", "/tmp/st u v w")
trackpacker.pack_files(
"archive1",
Expand All @@ -178,15 +184,17 @@ def test_pack_files_replaces_blanks_in_names(self, zip_mock):
)


def _files_in_dir(dirpath, filenames):
def _files_in_dir(dirpath: str, filenames: list[str]) -> list[str]:
return [os.path.join(dirpath, file) for file in filenames]


def _create_walk_files(files):
def _create_walk_files(files: list[str]):
return iter([("proj_export_dir", [], files)])


def _create_zip_mock_calls(archive_name, proj_export_dir, files):
def _create_zip_mock_calls(
archive_name: str, proj_export_dir: str, files: dict[str, str]
):
call_list = [
call(os.path.join(proj_export_dir, f"{archive_name}.zip"), "w"),
call().__enter__(), # pylint: disable=unnecessary-dunder-call
Expand Down
11 changes: 6 additions & 5 deletions trackpack/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,24 @@

import sys

from trackpack import cli, config
from trackpack import cli
from trackpack.config import Config
from trackpack.trackpacker import TrackPacker


def __fail(msg):
def __fail(msg: str) -> None:
print(f"ERROR: {msg}")
sys.exit(1)


def __read_config(filename):
def __read_config(filename: str) -> Config:
with open(filename, "r", encoding="utf-8") as config_file:
cfg = config.Config()
cfg = Config()
cfg.load_from_yaml(config_file)
return cfg


def main():
def main() -> None:
args = cli.parse_args(sys.argv[1:])

if args.command == "pack":
Expand Down
2 changes: 1 addition & 1 deletion trackpack/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
from trackpack.version import __version__


def parse_args(args):
def parse_args(args: list[str]) -> argparse.Namespace:
parser = argparse.ArgumentParser(
prog="trackpack", description="Audio tracks packaging"
)
Expand Down
10 changes: 5 additions & 5 deletions trackpack/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,32 @@


class Config:
def __init__(self):
def __init__(self) -> None:
self.name = "unnamed"
self._archive_name = "unnamed"
self.export_dir = "Export"
self.append_date = False

@property
def archive_name(self):
def archive_name(self) -> str:
if self.append_date:
return "-".join((self._archive_name, date.today().strftime("%Y-%m-%d")))
return self._archive_name

@archive_name.setter
def archive_name(self, archive_name):
def archive_name(self, archive_name: str) -> None:
if archive_name.endswith(".zip"):
self._archive_name = archive_name[:-4]
else:
self._archive_name = archive_name

def load_from_yaml(self, yaml_content):
def load_from_yaml(self, yaml_content) -> None:
config = yaml.safe_load(yaml_content)
self.name = config["name"]
self.archive_name = config.get("archive_name", self.name)
self.append_date = config.get("append_date", False)

def load_from_cli_args(self, cli_args):
def load_from_cli_args(self, cli_args) -> None:
if cli_args.archive_name:
self.archive_name = cli_args.archive_name
if cli_args.append_date:
Expand Down
8 changes: 4 additions & 4 deletions trackpack/trackpacker.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ class MissingFileException(Exception):


class TrackPacker:
def __init__(self, project_name, export_dir):
def __init__(self, project_name: str, export_dir: str) -> None:
self.__project_name = project_name
self.__export_dir = export_dir

def discover_audiofiles(self, explicit_files=None):
def discover_audiofiles(self, explicit_files: list[str] | None = None):
(_, _, filenames) = next(os.walk(self.__export_dir))
master = f"{self.__project_name}.wav"
files = list(filter(lambda f: f.endswith(".wav"), filenames))
Expand All @@ -49,14 +49,14 @@ def discover_audiofiles(self, explicit_files=None):

return (master, [os.path.abspath(file) for file in files])

def pack_files(self, archive_name, files):
def pack_files(self, archive_name: str, files: list[str]):
with ZipFile(
f"{os.path.join(self.__export_dir, archive_name)}.zip", "w"
) as archive:
for file in files:
archive.write(file, self.__normalize_stem_name(os.path.basename(file)))

def __normalize_stem_name(self, stem_name):
def __normalize_stem_name(self, stem_name: str) -> str:
if stem_name.startswith(self.__project_name):
stem_name = stem_name[len(self.__project_name) :]
return stem_name.strip().replace(" ", "-")