From 35bd7b2f5ac0304e9ecda8dfd8d10c110d54dc40 Mon Sep 17 00:00:00 2001 From: Tobias Schmidt Date: Mon, 30 Nov 2020 21:45:26 +0100 Subject: [PATCH 1/6] allow Paths in save() --- altair_saver/_utils.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/altair_saver/_utils.py b/altair_saver/_utils.py index be5bb37..0ff76af 100644 --- a/altair_saver/_utils.py +++ b/altair_saver/_utils.py @@ -2,6 +2,7 @@ from http import client import io import os +import pathlib import socket import subprocess import sys @@ -133,9 +134,10 @@ def temporary_filename( @contextlib.contextmanager -def maybe_open(fp: Union[IO, str], mode: str = "w") -> Iterator[IO]: - """Context manager to write to a file specified by filename or file-like object""" - if isinstance(fp, str): +def maybe_open(fp: Union[IO, str, pathlib.PurePath], mode: str = "w") -> Iterator[IO]: + """Context manager to write to a file specified by filename, Path or + file-like object""" + if isinstance(fp, str) or isinstance(fp, pathlib.PurePath): with open(fp, mode) as f: yield f elif isinstance(fp, io.TextIOBase) and "b" in mode: @@ -150,11 +152,13 @@ def maybe_open(fp: Union[IO, str], mode: str = "w") -> Iterator[IO]: yield fp -def extract_format(fp: Union[IO, str]) -> str: - """Extract the altair_saver output format from a file or filename.""" +def extract_format(fp: Union[IO, str, pathlib.PurePath]) -> str: + """Extract the altair_saver output format from a file, filename or Path.""" filename: Optional[str] if isinstance(fp, str): filename = fp + elif isinstance(fp, pathlib.PurePath): + filename = str(fp) else: filename = getattr(fp, "name", None) if filename is None: From 0b7558bb5f80313d3110f4e84f05b56114787900 Mon Sep 17 00:00:00 2001 From: Tobias Schmidt Date: Mon, 30 Nov 2020 21:49:04 +0100 Subject: [PATCH 2/6] black formatting fixes --- altair_saver/savers/_selenium.py | 9 +++++++-- altair_saver/savers/tests/test_html.py | 4 +++- altair_saver/savers/tests/test_node.py | 4 +++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/altair_saver/savers/_selenium.py b/altair_saver/savers/_selenium.py index 0ac3208..6839000 100644 --- a/altair_saver/savers/_selenium.py +++ b/altair_saver/savers/_selenium.py @@ -215,11 +215,16 @@ def _serve(cls, content: str, js_resources: Dict[str, str]) -> str: if cls._provider is None: cls._provider = Provider() resource = cls._provider.create( - content=content, route="", headers={"Access-Control-Allow-Origin": "*"}, + content=content, + route="", + headers={"Access-Control-Allow-Origin": "*"}, ) cls._resources[resource.url] = resource for route, content in js_resources.items(): - cls._resources[route] = cls._provider.create(content=content, route=route,) + cls._resources[route] = cls._provider.create( + content=content, + route=route, + ) return resource.url @classmethod diff --git a/altair_saver/savers/tests/test_html.py b/altair_saver/savers/tests/test_html.py index 6899fec..b3c2183 100644 --- a/altair_saver/savers/tests/test_html.py +++ b/altair_saver/savers/tests/test_html.py @@ -75,7 +75,9 @@ def test_html_save( @pytest.mark.parametrize("embed_options", [None, {"theme": "dark"}]) @pytest.mark.parametrize("case, data", get_testcases()) def test_html_mimebundle( - case: str, data: Dict[str, Any], embed_options: Optional[dict], + case: str, + data: Dict[str, Any], + embed_options: Optional[dict], ) -> None: saver = HTMLSaver(data["vega-lite"], embed_options=embed_options) bundle = saver.mimebundle("html") diff --git a/altair_saver/savers/tests/test_node.py b/altair_saver/savers/tests/test_node.py index 568d4bc..997794d 100644 --- a/altair_saver/savers/tests/test_node.py +++ b/altair_saver/savers/tests/test_node.py @@ -112,7 +112,9 @@ def exec_path(name: str) -> str: @pytest.mark.parametrize("suppress_warnings", [True, False]) def test_stderr_suppression( - interactive_spec: JSONDict, suppress_warnings: bool, capsys: SysCapture, + interactive_spec: JSONDict, + suppress_warnings: bool, + capsys: SysCapture, ) -> None: message = "WARN Can not resolve event source: window" From 486bf7f53051c42237d90eeb4b9b4a8cc3de9e82 Mon Sep 17 00:00:00 2001 From: Tobias Schmidt Date: Tue, 1 Dec 2020 16:07:02 +0100 Subject: [PATCH 3/6] improve and consolidate tests for format inference --- altair_saver/tests/test_utils.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/altair_saver/tests/test_utils.py b/altair_saver/tests/test_utils.py index ae5840b..b52154b 100644 --- a/altair_saver/tests/test_utils.py +++ b/altair_saver/tests/test_utils.py @@ -1,5 +1,6 @@ import http import io +import pathlib import socket import subprocess import tempfile @@ -43,21 +44,22 @@ def request(*args: Any, **kwargs: Any) -> None: ("vl.json", "vega-lite"), ], ) -@pytest.mark.parametrize("use_filename", [True, False]) -def test_extract_format(ext: str, fmt: str, use_filename: bool) -> None: - if use_filename: +@pytest.mark.parametrize("fp_type", ['string', 'path', 'pointer', 'stream']) +def test_extract_format(ext: str, fmt: str, fp_type: str) -> None: + if fp_type == 'string': filename = f"chart.{ext}" assert extract_format(filename) == fmt - else: + elif fp_type == 'path': + filepath = pathlib.Path(f"chart.{ext}") + assert extract_format(filepath) == fmt + elif fp_type == 'pointer': with tempfile.NamedTemporaryFile(suffix=f".{ext}") as fp: assert extract_format(fp) == fmt - - -def test_extract_format_failure() -> None: - fp = io.StringIO() - with pytest.raises(ValueError) as err: - extract_format(fp) - assert f"Cannot infer format from {fp}" in str(err.value) + elif fp_type == 'stream': + fp = io.StringIO() + with pytest.raises(ValueError) as err: + extract_format(fp) + assert f"Cannot infer format from {fp}" in str(err.value) @pytest.mark.parametrize("mode", ["w", "wb"]) From aad700a8bb9ebeee547fc5f4600eaecba887302f Mon Sep 17 00:00:00 2001 From: Tobias Schmidt Date: Tue, 1 Dec 2020 16:07:31 +0100 Subject: [PATCH 4/6] test maybe_open on paths --- altair_saver/tests/test_utils.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/altair_saver/tests/test_utils.py b/altair_saver/tests/test_utils.py index b52154b..2c71b13 100644 --- a/altair_saver/tests/test_utils.py +++ b/altair_saver/tests/test_utils.py @@ -63,11 +63,15 @@ def test_extract_format(ext: str, fmt: str, fp_type: str) -> None: @pytest.mark.parametrize("mode", ["w", "wb"]) -def test_maybe_open_filename(mode: str) -> None: +@pytest.mark.parametrize("fp_type", ["string", "path"]) +def test_maybe_open_filename(mode: str, fp_type: str) -> None: content_raw = "testing maybe_open with filename\n" content = content_raw.encode() if "b" in mode else content_raw with temporary_filename() as filename: + if fp_type == "path": + filename = pathlib.Path(filename) + with maybe_open(filename, mode) as f: f.write(content) with open(filename, "rb" if "b" in mode else "r") as f: From 56e29b826a09086342108e7a51a11745aa283cb6 Mon Sep 17 00:00:00 2001 From: Tobias Schmidt Date: Tue, 1 Dec 2020 16:09:20 +0100 Subject: [PATCH 5/6] black fixes --- altair_saver/tests/test_utils.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/altair_saver/tests/test_utils.py b/altair_saver/tests/test_utils.py index 2c71b13..8847aaa 100644 --- a/altair_saver/tests/test_utils.py +++ b/altair_saver/tests/test_utils.py @@ -44,18 +44,18 @@ def request(*args: Any, **kwargs: Any) -> None: ("vl.json", "vega-lite"), ], ) -@pytest.mark.parametrize("fp_type", ['string', 'path', 'pointer', 'stream']) +@pytest.mark.parametrize("fp_type", ["string", "path", "pointer", "stream"]) def test_extract_format(ext: str, fmt: str, fp_type: str) -> None: - if fp_type == 'string': + if fp_type == "string": filename = f"chart.{ext}" assert extract_format(filename) == fmt - elif fp_type == 'path': + elif fp_type == "path": filepath = pathlib.Path(f"chart.{ext}") assert extract_format(filepath) == fmt - elif fp_type == 'pointer': + elif fp_type == "pointer": with tempfile.NamedTemporaryFile(suffix=f".{ext}") as fp: assert extract_format(fp) == fmt - elif fp_type == 'stream': + elif fp_type == "stream": fp = io.StringIO() with pytest.raises(ValueError) as err: extract_format(fp) From 9844c237794d012df28b02e6c5608345fa929b2d Mon Sep 17 00:00:00 2001 From: Tobias Schmidt Date: Tue, 1 Dec 2020 19:36:47 +0100 Subject: [PATCH 6/6] mypy fixes --- altair_saver/tests/test_utils.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/altair_saver/tests/test_utils.py b/altair_saver/tests/test_utils.py index 8847aaa..1c79083 100644 --- a/altair_saver/tests/test_utils.py +++ b/altair_saver/tests/test_utils.py @@ -56,25 +56,27 @@ def test_extract_format(ext: str, fmt: str, fp_type: str) -> None: with tempfile.NamedTemporaryFile(suffix=f".{ext}") as fp: assert extract_format(fp) == fmt elif fp_type == "stream": - fp = io.StringIO() + string_io = io.StringIO() with pytest.raises(ValueError) as err: - extract_format(fp) - assert f"Cannot infer format from {fp}" in str(err.value) + extract_format(string_io) + assert f"Cannot infer format from {string_io}" in str(err.value) @pytest.mark.parametrize("mode", ["w", "wb"]) @pytest.mark.parametrize("fp_type", ["string", "path"]) def test_maybe_open_filename(mode: str, fp_type: str) -> None: - content_raw = "testing maybe_open with filename\n" + content_raw = "testing maybe_open with filename or path\n" content = content_raw.encode() if "b" in mode else content_raw with temporary_filename() as filename: if fp_type == "path": - filename = pathlib.Path(filename) + fp = pathlib.Path(filename) + elif fp_type == "string": + fp = filename - with maybe_open(filename, mode) as f: + with maybe_open(fp, mode) as f: f.write(content) - with open(filename, "rb" if "b" in mode else "r") as f: + with open(fp, "rb" if "b" in mode else "r") as f: assert f.read() == content