Skip to content

Commit

Permalink
Drop html output support
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardobranco777 committed Sep 1, 2024
1 parent bd7baa8 commit 5c1be46
Show file tree
Hide file tree
Showing 7 changed files with 9 additions and 161 deletions.
1 change: 0 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ RUN zypper addrepo https://download.opensuse.org/repositories/SUSE:/CA/openSUSE_
python3-apache-libcloud \
python3-cachetools \
python3-cryptography \
python3-Jinja2 \
python3-python-dateutil \
python3-pytz \
python3-PyYAML && \
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Docker image available at `ghcr.io/ricardobranco777/cloudview:latest`
## Usage

```
usage: cloudview.py [-h] [-c CONFIG] [-f FORMAT] [-l {none,debug,info,warning,error,critical}] [-o {text,html,json}] [-P {ec2,gce,azure_arm,openstack}] [-r]
usage: cloudview.py [-h] [-c CONFIG] [-f FORMAT] [-l {none,debug,info,warning,error,critical}] [-o {text,json}] [-P {ec2,gce,azure_arm,openstack}] [-r]
[-s {name,state,time}] [-S {error,migrating,normal,paused,pending,rebooting,reconfiguring,running,starting,stopped,stopping,suspended,terminated,unknown,updating}]
[-t TIME_FORMAT] [-v] [--version]
Expand All @@ -25,7 +25,7 @@ options:
output fields (default: provider,name,size,state,time,location)
-l {none,debug,info,warning,error,critical}, --log {none,debug,info,warning,error,critical}
logging level (default: error)
-o {text,html,json}, --output {text,html,json}
-o {text,json}, --output {text,json}
output type (default: text)
-P {ec2,gce,azure_arm,openstack}, --providers {ec2,gce,azure_arm,openstack}
list only specified providers (default: None)
Expand Down
9 changes: 2 additions & 7 deletions cloudview/cloudview.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from concurrent.futures import ThreadPoolExecutor
from operator import itemgetter
from typing import Any
from urllib.parse import urlencode

import yaml
from libcloud.compute.types import Provider, LibcloudError
Expand Down Expand Up @@ -85,10 +84,6 @@ def print_instances(client: CSP) -> None:
)
for instance in instances:
instance.provider = "/".join([instance.provider, instance.cloud])
if args.output == "html":
params = urlencode(instance.params)
resource = "/".join([instance.provider.lower(), f"{instance.id}?{params}"])
instance.href = f"instance/{resource}"
assert not isinstance(instance.time, str)
instance.time = dateit(instance.time, args.time)
Output().info(instance)
Expand Down Expand Up @@ -133,7 +128,7 @@ def parse_args() -> argparse.Namespace:
"-o",
"--output",
default="text",
choices=["text", "html", "json"],
choices=["text", "json"],
help="output type",
)
argparser.add_argument(
Expand Down Expand Up @@ -200,7 +195,7 @@ def main() -> None:
if args.verbose:
keys |= {"id": ""}

Output(type=args.output.lower(), keys=keys, refresh_seconds=600)
Output(type=args.output.lower(), keys=keys)
print_info()


Expand Down
18 changes: 0 additions & 18 deletions cloudview/footer.html

This file was deleted.

34 changes: 0 additions & 34 deletions cloudview/header.html

This file was deleted.

49 changes: 4 additions & 45 deletions cloudview/output.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,16 @@
"""
Handle tabular output in these formats: text, json & html
Handle tabular output in these formats: text, json
"""

import html
import json
import os

from jinja2 import Template

from cloudview.singleton import Singleton


def html_tag(tag: str, content: str = "", **kwargs) -> str:
"""
HTML tag
"""
attributes = " ".join(
f'{key}="{value}"' for key, value in kwargs.items() if value is not None
)
if attributes:
return f"<{tag} {attributes}>{content}</{tag}>"
return f"<{tag}>{content}</{tag}>"


# pylint: disable=redefined-builtin
class Output(metaclass=Singleton):
"""
Helper class to handle tabular output in text, json or html
Helper class to handle tabular output in text, json
"""

def __init__(
Expand All @@ -36,12 +20,11 @@ def __init__(
**kwargs,
) -> None:
"""
type must be either text, json or html
type must be either text, json
fmt is the format string used for text
keys are the items in the dictionary
seconds is the refresh time for HTML output
"""
if type not in ("text", "json", "html"):
if type not in ("text", "json"):
raise ValueError(f"Invalid type: {type}")
self._type = type
if isinstance(keys, (list, tuple)):
Expand All @@ -63,15 +46,6 @@ def header(self) -> None:
print(
self._output_format.format_map({key: key.upper() for key in self._keys})
)
elif self._type == "html":
cells = "".join(html_tag("th", key.upper()) for key in self._keys)
table_header = html_tag("thead", html_tag("tr", cells))
table_header = f'<table style="width:100%">{table_header}<tbody>'
with open(
os.path.join(os.path.dirname(__file__), "header.html"), encoding="utf-8"
) as file:
header = file.read()
print(Template(header).render(**self._kwargs), table_header)

def info(self, item) -> None:
"""
Expand All @@ -84,25 +58,10 @@ def info(self, item) -> None:
print(self._output_format.format_map(item.__dict__))
elif self._type == "json":
self._items.append(item if isinstance(item, dict) else item.__dict__)
elif self._type == "html":
info = {
k: html.escape(item[k]) if isinstance(item[k], str) else item[k]
for k in self._keys
}
info["name"] = html_tag("a", html.escape(item["name"]), href=item["href"])
cells = "".join(html_tag("td", info[key]) for key in self._keys)
print(html_tag("tr", cells))

def footer(self) -> None:
"""
Print the footer for output
"""
if self._type == "json":
print(json.dumps(self._items, indent=2, default=str))
elif self._type == "html":
with open(
os.path.join(os.path.dirname(__file__), "footer.html"), encoding="utf-8"
) as file:
footer = file.read()
table_footer = "</tbody></table>"
print(table_footer, Template(footer).render(**self._kwargs))
55 changes: 1 addition & 54 deletions tests/test_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import pytest

from cloudview.instance import Instance
from cloudview.output import Output, html_tag
from cloudview.output import Output


@pytest.fixture
Expand All @@ -18,11 +18,6 @@ def json_output():
return Output(type="json")


@pytest.fixture
def html_output():
return Output(type="html", keys=["name", "age", "href"])


# Use the "monkeypatch" fixture to reset the singleton instance before each test
@pytest.fixture(autouse=True)
def reset_singleton(monkeypatch):
Expand All @@ -48,29 +43,6 @@ def test_text_output_info(text_output, capsys):
assert captured.out == expected_info


def test_html_output_header(html_output, capsys):
expected_header = "<th>NAME</th>"
html_output.header()
captured = capsys.readouterr()
assert expected_header in captured.out


def test_html_output_info(html_output, capsys):
expected_info = (
'<tr><td><a href="john.html">John</a></td><td>30</td><td>john.html</td></tr>'
)
item = {"name": "John", "age": 30, "href": "john.html"}
html_output.info(item)
captured = capsys.readouterr()
assert expected_info in captured.out


def test_html_output_footer(html_output, capsys):
html_output.footer()
captured = capsys.readouterr()
assert "</html>" in captured.out


def test_json_output_dict(json_output, capsys):
json_output.header()
info = {"name": "John", "age": 30}
Expand Down Expand Up @@ -98,28 +70,3 @@ def test_json_output_obj(json_output, capsys):
json_output.footer()
captured = capsys.readouterr()
assert [info.__dict__] == json.loads(captured.out)


# Test cases for the html_tag function
def test_html_tag_basic():
# Test with a simple HTML tag
result = html_tag("div", "Hello, World!")
assert result == "<div>Hello, World!</div>"


def test_html_tag_with_attributes():
# Test with attributes
result = html_tag("a", "Click me", href="https://example.com", target="_blank")
assert result == '<a href="https://example.com" target="_blank">Click me</a>'


def test_html_tag_empty_content():
# Test with empty content
result = html_tag("p")
assert result == "<p></p>"


def test_html_tag_empty_attributes():
# Test with empty attributes
result = html_tag("span", "This is a span", **{})
assert result == "<span>This is a span</span>"

0 comments on commit 5c1be46

Please sign in to comment.