Skip to content

Commit

Permalink
Work around project path set to recording path
Browse files Browse the repository at this point in the history
* Override the path property of `reapy.core.Project` in our own subclass
  • Loading branch information
john-kurkowski committed Nov 2, 2023
1 parent 508ec0c commit 65174da
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 8 deletions.
26 changes: 22 additions & 4 deletions src/music/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,29 @@
T = TypeVar("T")


class ExtendedProject(reapy.core.Project):
"""Extend reapy.core.Project with additional properties."""

@property
def path(self) -> str:
"""Override. Get the path containing the project.
Works around a bug in reapy 0.10.0's implementation of `Project.path`,
which actually gets the _recording_ path of the project.
"""
filename = str(reapy.RPR.EnumProjects(-1, None, 999)[2]) # type: ignore[attr-defined]
return str(Path(filename).parent)


def assert_exhaustiveness(no_return: NoReturn) -> NoReturn: # pragma: no cover
"""Provide an assertion at type-check time that this function is never called."""
raise AssertionError(f"Invalid value: {no_return!r}")


def find_project(project_dir: Path | None = None) -> reapy.core.Project:
def find_project(project_dir: Path | None = None) -> ExtendedProject:
"""Find the target Reaper project, or current project if unspecified."""
try:
project = reapy.Project()
project = ExtendedProject()
except AttributeError as aterr:
if "module" in str(aterr) and "reascript_api" in str(aterr):
raise Exception(
Expand All @@ -36,7 +50,8 @@ def find_project(project_dir: Path | None = None) -> reapy.core.Project:
if project_dir.suffix == ".rpp"
else project_dir / f"{project_dir.name}.rpp"
)
return reapy.open_project(str(project_file))
reapy.RPR.Main_openProject(str(project_file)) # type: ignore[attr-defined]
return ExtendedProject()


def recurse_property(prop: str, obj: T | None) -> Iterator[T]:
Expand All @@ -47,7 +62,10 @@ def recurse_property(prop: str, obj: T | None) -> Iterator[T]:


def set_param_value(param: reapy.core.FXParam, value: float) -> None:
"""Set a parameter's value. Work around bug with reapy 0.10's setter."""
"""Set a parameter's value.
Works around bug with reapy 0.10's setter.
"""
parent_fx = param.parent_list.parent_fx
parent = parent_fx.parent
param.functions["SetParamNormalized"]( # type: ignore[operator]
Expand Down
10 changes: 6 additions & 4 deletions tests/test_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,10 @@ def render_mocks(
threshold.functions = {"SetParamNormalized": mock.Mock()}

with (
mock.patch("reapy.open_project") as mock_open_project,
mock.patch("reapy.Project") as mock_project_class,
mock.patch(
"reapy.reascript_api.Main_openProject", create=True
) as mock_open_project,
mock.patch("music.util.ExtendedProject") as mock_project_class,
mock.patch(
"music.render.RenderResult.duration_delta", new_callable=mock.PropertyMock
) as mock_duration_delta,
Expand All @@ -92,7 +94,7 @@ def render_mocks(
) as mock_set_int_config_var,
mock.patch("music.upload.main") as mock_upload,
):
project = mock_open_project.return_value = mock_project_class.return_value
project = mock_project_class.return_value

render_patterns = []

Expand Down Expand Up @@ -196,7 +198,7 @@ def test_render_result_render_speedup(
assert subprocess.call_args_list == snapshot


@mock.patch("reapy.Project")
@mock.patch("music.util.ExtendedProject")
def test_main_reaper_not_running(project: mock.Mock) -> None:
"""Test command handling when Reaper is not running."""
project.side_effect = AttributeError("module doesn't have reascript_api, yo")
Expand Down

0 comments on commit 65174da

Please sign in to comment.