From 5e192b80c3c51a3e9621136aff0d386b6a20a405 Mon Sep 17 00:00:00 2001 From: Jacob Peck Date: Wed, 6 Mar 2024 08:37:05 -0500 Subject: [PATCH 1/4] Added '--orientation' option to pagerotate command, to allow conditionally rotating a page to a target orientation. --- vpype_cli/operations.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/vpype_cli/operations.py b/vpype_cli/operations.py index eff7aa28..5bc20620 100644 --- a/vpype_cli/operations.py +++ b/vpype_cli/operations.py @@ -662,12 +662,21 @@ def layout( is_flag=True, help="Rotate clockwise instead of the default counter-clockwise", ) +@click.option( + "--orientation", + "-o", + type=click.Choice(["any", "portrait", "landscape"]), + default="any", + help="Conditionally rotate only if the final orientation matches this option", +) @global_processor -def pagerotate(document: vp.Document, clockwise: bool): +def pagerotate(document: vp.Document, clockwise: bool, orientation: str): """Rotate the page by 90 degrees. This command rotates the page by 90 degrees counter-clockwise. If the `--clockwise` option - is passed, it rotates the page clockwise instead. + is passed, it rotates the page clockwise instead. If the `--orientation` option is given + a value of either 'portrait' or 'landscape', the page will only be rotated if the final + orientation would match that choice. Note: if the page size is not defined, an error is printed and the page is not rotated. """ @@ -677,6 +686,11 @@ def pagerotate(document: vp.Document, clockwise: bool): return document w, h = page_size + # check orientation constraint, and do nothing if target orientation + # won't match desired result + if (orientation == "portrait" and h > w) or (orientation == "landscape" and w > h): + return document + if clockwise: document.rotate(math.pi / 2) document.translate(h, 0) From c0f98c0550a627d15bce79bcad1fcd3e6a2681a8 Mon Sep 17 00:00:00 2001 From: Jacob Peck Date: Wed, 6 Mar 2024 15:36:07 -0500 Subject: [PATCH 2/4] Added warning message to pagerotate if not rotating due to page orientation target. --- vpype_cli/operations.py | 1 + 1 file changed, 1 insertion(+) diff --git a/vpype_cli/operations.py b/vpype_cli/operations.py index 5bc20620..23b63724 100644 --- a/vpype_cli/operations.py +++ b/vpype_cli/operations.py @@ -689,6 +689,7 @@ def pagerotate(document: vp.Document, clockwise: bool, orientation: str): # check orientation constraint, and do nothing if target orientation # won't match desired result if (orientation == "portrait" and h > w) or (orientation == "landscape" and w > h): + logging.warning("pagerotate: page already in target orientation, page not rotated.") return document if clockwise: From 635836eabe8b5817da4fecb4f9222288982c4073 Mon Sep 17 00:00:00 2001 From: Jacob Peck Date: Thu, 7 Mar 2024 09:04:03 -0500 Subject: [PATCH 3/4] - Swapped `click.Choice` for `ChoiceType` for `--orientation` option of `pagerotate` command, per @abey79 - Added new tests for `pagerotate --orientation` - Updated CHANGELOG.md --- CHANGELOG.md | 2 +- tests/test_commands.py | 22 ++++++++++++++++++++++ vpype_cli/operations.py | 16 +++++++++++----- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2b126b5..6806b92f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ Release date: UNRELEASED ### New features and improvements -* ... +* Added a `--orientation` option to the `pagerotate` command to conditionally rotate the page to a target orientation (thanks to @gatesphere) (#705) ### Bug fixes diff --git a/tests/test_commands.py b/tests/test_commands.py index 53fdbd77..414372d5 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -728,6 +728,28 @@ def test_pagerotate_error(caplog): assert "page size is not defined, page not rotated" in caplog.text +def test_pagerotate_orientation(): + doc = vpype_cli.execute("random pagesize a4 pagerotate -o landscape") + assert doc.page_size == pytest.approx((1122.5196850393702, 793.7007874015749)) + + doc = vpype_cli.execute("random pagesize a4 pagerotate -cw -o landscape") + assert doc.page_size == pytest.approx((1122.5196850393702, 793.7007874015749)) + + doc = vpype_cli.execute("random pagesize --landscape a4 pagerotate -o portrait") + assert doc.page_size == pytest.approx((793.7007874015749, 1122.5196850393702)) + + doc = vpype_cli.execute("random pagesize --landscape a4 pagerotate -cw -o portrait") + assert doc.page_size == pytest.approx((793.7007874015749, 1122.5196850393702)) + + +def test_pagerotate_orientation_error(): + doc = vpype_cli.execute("random pagesize a4 pagerotate -o portrait") + assert doc.page_size == pytest.approx((793.7007874015749, 1122.5196850393702)) + + doc = vpype_cli.execute("random pagesize --landscape a4 pagerotate -o landscape") + assert doc.page_size == pytest.approx((1122.5196850393702, 793.7007874015749)) + + def test_help(runner): res = runner.invoke(cli, "--help") diff --git a/vpype_cli/operations.py b/vpype_cli/operations.py index 23b63724..f2f7fc6c 100644 --- a/vpype_cli/operations.py +++ b/vpype_cli/operations.py @@ -11,7 +11,14 @@ from .cli import cli from .decorators import global_processor, layer_processor -from .types import IntegerType, LayerType, LengthType, PageSizeType, multiple_to_layer_ids +from .types import ( + ChoiceType, + IntegerType, + LayerType, + LengthType, + PageSizeType, + multiple_to_layer_ids, +) __all__ = ( "crop", @@ -665,12 +672,11 @@ def layout( @click.option( "--orientation", "-o", - type=click.Choice(["any", "portrait", "landscape"]), - default="any", + type=ChoiceType(["portrait", "landscape"]), help="Conditionally rotate only if the final orientation matches this option", ) @global_processor -def pagerotate(document: vp.Document, clockwise: bool, orientation: str): +def pagerotate(document: vp.Document, clockwise: bool, orientation: str | None): """Rotate the page by 90 degrees. This command rotates the page by 90 degrees counter-clockwise. If the `--clockwise` option @@ -689,7 +695,7 @@ def pagerotate(document: vp.Document, clockwise: bool, orientation: str): # check orientation constraint, and do nothing if target orientation # won't match desired result if (orientation == "portrait" and h > w) or (orientation == "landscape" and w > h): - logging.warning("pagerotate: page already in target orientation, page not rotated.") + logging.debug("pagerotate: page already in target orientation, page not rotated") return document if clockwise: From 593c5bd2da6879f08ec17fa1199322fff1b52c87 Mon Sep 17 00:00:00 2001 From: Jacob Peck Date: Thu, 7 Mar 2024 12:04:59 -0500 Subject: [PATCH 4/4] Add sanity checks to pagerotate for orientation option. --- vpype_cli/operations.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vpype_cli/operations.py b/vpype_cli/operations.py index f2f7fc6c..1ddbade8 100644 --- a/vpype_cli/operations.py +++ b/vpype_cli/operations.py @@ -692,6 +692,13 @@ def pagerotate(document: vp.Document, clockwise: bool, orientation: str | None): return document w, h = page_size + # sanity checks + if orientation is not None and orientation not in ["portrait", "landscape"]: + logging.warning( + f"pagerotate: orientation value '{orientation}' not one of 'portrait', 'landscape'" + ) + return document + # check orientation constraint, and do nothing if target orientation # won't match desired result if (orientation == "portrait" and h > w) or (orientation == "landscape" and w > h):