From 6bdfa9e645648661a26cf0b2b6017ea2d35acf7f Mon Sep 17 00:00:00 2001 From: thatmattlove Date: Thu, 16 Sep 2021 15:57:33 -0700 Subject: [PATCH] Fix string output type checks --- hyperglass/execution/drivers/_common.py | 9 +++++---- hyperglass/execution/main.py | 8 +++++++- hyperglass/plugins/_builtin/remove_command.py | 4 ++-- hyperglass/plugins/_output.py | 5 +++-- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/hyperglass/execution/drivers/_common.py b/hyperglass/execution/drivers/_common.py index 085af2d..dbcee04 100644 --- a/hyperglass/execution/drivers/_common.py +++ b/hyperglass/execution/drivers/_common.py @@ -1,17 +1,18 @@ """Base Connection Class.""" # Standard Library +import typing as t from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Union, Sequence # Project from hyperglass.log import log +from hyperglass.types import Series from hyperglass.plugins import OutputPluginManager # Local from ._construct import Construct -if TYPE_CHECKING: +if t.TYPE_CHECKING: # Project from hyperglass.models.api import Query from hyperglass.models.data import OutputDataModel @@ -37,7 +38,7 @@ class Connection(ABC): """Return a preconfigured sshtunnel.SSHTunnelForwarder instance.""" pass - async def response(self, output: Sequence[str]) -> Union["OutputDataModel", str]: + async def response(self, output: Series[str]) -> t.Union["OutputDataModel", str]: """Send output through common parsers.""" log.debug("Pre-parsed responses:\n{}", output) @@ -47,7 +48,7 @@ class Connection(ABC): ) if response is None: - response = "\n\n".join(output) + response = () log.debug("Post-parsed responses:\n{}", response) return response diff --git a/hyperglass/execution/main.py b/hyperglass/execution/main.py index 1b5a856..6b5f8cc 100644 --- a/hyperglass/execution/main.py +++ b/hyperglass/execution/main.py @@ -13,6 +13,7 @@ from typing import TYPE_CHECKING, Any, Dict, Union, Callable # Project from hyperglass.log import log from hyperglass.state import use_state +from hyperglass.util.typing import is_series from hyperglass.exceptions.public import DeviceTimeout, ResponseEmpty if TYPE_CHECKING: @@ -71,7 +72,12 @@ async def execute(query: "Query") -> Union["OutputDataModel", str]: output = await driver.response(response) - if isinstance(output, str): + if is_series(output): + if len(output) == 0: + raise ResponseEmpty(query=query) + output = "\n\n".join(output) + + elif isinstance(output, str): # If the output is a string (not structured) and is empty, # produce an error. if output == "" or output == "\n": diff --git a/hyperglass/plugins/_builtin/remove_command.py b/hyperglass/plugins/_builtin/remove_command.py index b730a5c..60f0d09 100644 --- a/hyperglass/plugins/_builtin/remove_command.py +++ b/hyperglass/plugins/_builtin/remove_command.py @@ -7,7 +7,7 @@ from typing import TYPE_CHECKING, Sequence from pydantic import PrivateAttr # Project -from hyperglass.util.typing import is_type +from hyperglass.util.typing import is_series # Local from .._output import OutputType, OutputPlugin @@ -36,7 +36,7 @@ class RemoveCommand(OutputPlugin): return "\n".join(output_out) - if is_type(device_output, str): + if is_series(device_output): return tuple(_remove_command(o) for o in device_output) return device_output diff --git a/hyperglass/plugins/_output.py b/hyperglass/plugins/_output.py index a30d2e1..9efee14 100644 --- a/hyperglass/plugins/_output.py +++ b/hyperglass/plugins/_output.py @@ -1,10 +1,11 @@ """Device output plugins.""" # Standard Library -from typing import TYPE_CHECKING, Union, Sequence +from typing import TYPE_CHECKING, Union # Project from hyperglass.log import log +from hyperglass.types import Series # Local from ._base import DirectivePlugin, DeviceTypePlugin, HyperglassPlugin @@ -14,7 +15,7 @@ if TYPE_CHECKING: from hyperglass.models.data import OutputDataModel from hyperglass.models.config.devices import Device -OutputType = Union["OutputDataModel", Sequence[str]] +OutputType = Union["OutputDataModel", Series[str]] class OutputPlugin(HyperglassPlugin, DirectivePlugin, DeviceTypePlugin):