Skip to content

Commit

Permalink
Chore: More code linting and formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
amotl committed Dec 1, 2024
1 parent 040fbfa commit 415c79f
Show file tree
Hide file tree
Showing 14 changed files with 158 additions and 56 deletions.
10 changes: 7 additions & 3 deletions grafanimate/animations.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@

class SequentialAnimation:
def __init__(
self, grafana: GrafanaWrapper, dashboard_uid: str = None, options: Munch = None
self,
grafana: GrafanaWrapper,
dashboard_uid: str = None,
options: Munch = None,
):
self.grafana = grafana
self.dashboard_uid = dashboard_uid
Expand Down Expand Up @@ -57,7 +60,7 @@ def run(self, sequence: AnimationSequence):
"image": image,
},
"frame": frame,
}
},
)

yield item
Expand All @@ -71,7 +74,8 @@ def render(self, frame: AnimationFrame):
logger.debug("Rendering image")
if self.options["exposure-time"] > 0:
logger.info(
"Waiting for %s seconds (exposure time)", self.options["exposure-time"]
"Waiting for %s seconds (exposure time)",
self.options["exposure-time"],
)
time.sleep(self.options["exposure-time"])

Expand Down
21 changes: 15 additions & 6 deletions grafanimate/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json
import logging
import os
import typing as t
from pathlib import Path

from docopt import DocoptExit, docopt
Expand All @@ -11,9 +12,12 @@
from grafanimate.core import get_scenario, make_grafana, run_animation_scenario
from grafanimate.media import produce_artifacts
from grafanimate.model import RenderingOptions
from grafanimate.spool import TemporaryStorage
from grafanimate.util import asbool, normalize_options, setup_logging

if t.TYPE_CHECKING:
from grafanimate.spool import TemporaryStorage


log = logging.getLogger(__name__)


Expand Down Expand Up @@ -138,12 +142,12 @@ def run():
output_path = os.environ.get("GRAFANIMATE_OUTPUT")
if not output_path:
raise DocoptExit(
"Error: Parameter --output or environment variable GRAFANIMATE_OUTPUT is mandatory"
"Error: Parameter --output or environment variable GRAFANIMATE_OUTPUT is mandatory",
)

if options["dashboard-view"] == "d-solo" and not options["panel-id"]:
raise DocoptExit(
"Error: Parameter --panel-id is mandatory for --dashboard-view=d-solo"
"Error: Parameter --panel-id is mandatory for --dashboard-view=d-solo",
)

options["exposure-time"] = float(options["exposure-time"])
Expand Down Expand Up @@ -175,17 +179,22 @@ def run():
scenario.dashboard_uid = options["dashboard-uid"]
if not scenario.dashboard_uid:
raise KeyError(
"Dashboard UID is mandatory, either supply it on the command line or via scenario file"
"Dashboard UID is mandatory, either supply it on the command line or via scenario file",
)

# Open a Grafana site in Firefox, using Marionette.
grafana = make_grafana(
scenario.grafana_url, scenario.dashboard_uid, options, options["headless"]
scenario.grafana_url,
scenario.dashboard_uid,
options,
options["headless"],
)

# Invoke pipeline: Run stop motion animation, producing single frames.
storage: TemporaryStorage = run_animation_scenario(
scenario=scenario, grafana=grafana, options=options
scenario=scenario,
grafana=grafana,
options=options,
)

# Define output filename pattern.
Expand Down
22 changes: 15 additions & 7 deletions grafanimate/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@


def make_grafana(
url: str, dashboard_uid: str, options: dict, headless=False
url: str,
dashboard_uid: str,
options: dict,
headless=False,
) -> GrafanaWrapper:
do_login = False
url = furl(url)
Expand Down Expand Up @@ -46,10 +49,11 @@ def make_grafana(
if str(url)[-1] != "/":
url = str(url) + "/"
url = str(url) + view + "/" + dashboard_uid + "/" + slug + query
print(url)
log.info(f"URL: {url}")

grafana = GrafanaWrapper(
baseurl=str(url), use_panel_events=options["use-panel-events"]
baseurl=str(url),
use_panel_events=options["use-panel-events"],
)
grafana.boot_firefox(headless=headless)
grafana.boot_grafana()
Expand Down Expand Up @@ -77,7 +81,7 @@ def get_scenario(source: str) -> AnimationScenario:

if scenario is None:
raise NotImplementedError(
f'Animation scenario "{source}" not found or implemented'
f'Animation scenario "{source}" not found or implemented',
)

scenario.source = source
Expand Down Expand Up @@ -105,10 +109,12 @@ def resolve_reference(module, symbol):


def run_animation_scenario(
scenario: AnimationScenario, grafana: GrafanaWrapper, options: Munch
scenario: AnimationScenario,
grafana: GrafanaWrapper,
options: Munch,
) -> TemporaryStorage:
log.info(
f"Running animation scenario at {scenario.grafana_url}, with dashboard UID {scenario.dashboard_uid}"
f"Running animation scenario at {scenario.grafana_url}, with dashboard UID {scenario.dashboard_uid}",
)

storage = TemporaryStorage()
Expand All @@ -129,7 +135,9 @@ def run_animation_scenario(

# Start the engines.
animation = SequentialAnimation(
grafana=grafana, dashboard_uid=scenario.dashboard_uid, options=animation_options
grafana=grafana,
dashboard_uid=scenario.dashboard_uid,
options=animation_options,
)
animation.start()

Expand Down
11 changes: 8 additions & 3 deletions grafanimate/grafana.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ class GrafanaWrapper(FirefoxMarionetteBase):
"""

def __init__(
self, baseurl: str = None, use_panel_events: bool = True, dry_run: bool = False
self,
baseurl: str = None,
use_panel_events: bool = True,
dry_run: bool = False,
):
self.baseurl = baseurl
self.use_panel_events = use_panel_events
Expand Down Expand Up @@ -93,7 +96,7 @@ def wait_all_data_received(self):
log.info('Waiting for "all-data-received" event')
waiter = Wait(self.marionette, timeout=20.0, interval=0.1)

def condition(marionette):
def condition(marionette): # noqa: ARG001
return self.calljs("grafanaStudio.hasAllData", silent=True)

try:
Expand Down Expand Up @@ -153,7 +156,9 @@ def run_javascript(self, sourcecode, silent=False):
if not silent:
log.debug("Running Javascript: %s", sourcecode)
return self.marionette.execute_script(
sourcecode, sandbox=None, new_sandbox=False
sourcecode,
sandbox=None,
new_sandbox=False,
)

def calljs(self, name, *args, silent=False):
Expand Down
4 changes: 2 additions & 2 deletions grafanimate/marionette.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ def shutdown(self):

if self.firefox_already_started:
logger.warning(
"Can not shutdown Firefox as it was already running before starting this program"
"Can not shutdown Firefox as it was already running before starting this program",
)
return False

Expand All @@ -171,7 +171,7 @@ def wait_for_element_tag(self, tagname):
Wait for element to appear.
"""
waiter = Wait(self.marionette, timeout=20.0, interval=0.1)
element = waiter.until(lambda m: self.find_tag(tagname))
element = waiter.until(lambda _: self.find_tag(tagname))
return element

def render_image(self, element=None):
Expand Down
9 changes: 7 additions & 2 deletions grafanimate/media.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@


def produce_artifacts(
input, output, scenario: AnimationScenario, options: RenderingOptions
input,
output,
scenario: AnimationScenario,
options: RenderingOptions,
):
# TODO: Can use dashboard title as output filename here?
# TODO: Can put `start` into filename?
Expand All @@ -17,7 +20,9 @@ def produce_artifacts(
# Compute input pattern and output file name.
input = os.path.join(str(input), "*.png")
output = str(output).format(
scenario=scenario_slug, title=title_slug, uid=scenario.dashboard_uid
scenario=scenario_slug,
title=title_slug,
uid=scenario.dashboard_uid,
)

# Produce output artifacts.
Expand Down
6 changes: 4 additions & 2 deletions grafanimate/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ def __init__(

def get_frames(self) -> Generator[AnimationFrame, None, None]:
timerange = Timerange(
start=self.start, stop=self.stop, recurrence=self.recurrence
start=self.start,
stop=self.stop,
recurrence=self.recurrence,
)

# until = datetime.now()
Expand All @@ -86,7 +88,7 @@ def get_frames(self) -> Generator[AnimationFrame, None, None]:
until=timerange.stop,
freq=self.recurrence.frequency,
interval=self.recurrence.interval,
)
),
)
# logger.info('Date range is: %s', daterange)

Expand Down
6 changes: 3 additions & 3 deletions grafanimate/postprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def to_video(self, source, target):
command = f"ffmpeg -framerate {self.options.video_framerate} -pattern_type glob -i '{source}' -c:v libx264 -vf 'pad=ceil(iw/2)*2:ceil(ih/2)*2,fps={self.options.video_fps},format=yuv420p' '{target}' -y"
logger.info(f"Rendering video: {target}")
logger.debug(command)
os.system(command)
os.system(command) # noqa: S605

def to_gif(self, source, target):
"""
Expand Down Expand Up @@ -81,11 +81,11 @@ def to_gif(self, source, target):
command = f"ffmpeg -i '{source}' -filter_complex 'fps={self.options.gif_fps},scale={self.options.gif_width}:-1:flags=lanczos,split [o1] [o2];[o1] palettegen [p]; [o2] [p] paletteuse' '{target}' -y"
logger.info("Rendering GIF: %s", target)
logger.debug(command)
os.system(command)
os.system(command) # noqa: S605

def upload_server(self, source):
command = f"make --makefile=/Users/amo/dev/hiveeyes/sources/documentation/Makefile ptrace source={source}"
os.system(command)
os.system(command) # noqa: S605

def render(self, source, target):
mp4 = target
Expand Down
20 changes: 15 additions & 5 deletions grafanimate/scenarios.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,15 @@ def ldi_all():
return [
# LDI, ramp-up
AnimationSequence(
start=datetime(2015, 10, 1), stop=datetime(2017, 1, 1), every="monthly"
start=datetime(2015, 10, 1),
stop=datetime(2017, 1, 1),
every="monthly",
),
# LDI, growth
AnimationSequence(
start=datetime(2017, 1, 1), stop=datetime.now(), every="weekly"
start=datetime(2017, 1, 1),
stop=datetime.now(),
every="weekly",
),
]

Expand All @@ -147,16 +151,22 @@ def ldi_with_gaps():
return [
# LDI, ramp-up
AnimationSequence(
start=datetime(2015, 10, 1), stop=datetime(2017, 1, 1), every="monthly"
start=datetime(2015, 10, 1),
stop=datetime(2017, 1, 1),
every="monthly",
),
# LDI, growth, with gap at 2018-04-29 - 2018-12-20
# TODO: Detect empty data from datasource through Grafana Sidecar and skip respective images.
AnimationSequence(
start=datetime(2017, 1, 1), stop=datetime(2018, 6, 5), every="weekly"
start=datetime(2017, 1, 1),
stop=datetime(2018, 6, 5),
every="weekly",
),
# LDI, until now
AnimationSequence(
start=datetime(2018, 12, 20), stop=datetime.now(), every="weekly"
start=datetime(2018, 12, 20),
stop=datetime.now(),
every="weekly",
),
]

Expand Down
22 changes: 15 additions & 7 deletions grafanimate/timecontrol.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,12 @@ def __iter__(self):

def print_intervals(intervals):
for interval in intervals:
print(f"{interval.start} - {interval.end}")
print(f"{interval.start} - {interval.end}") # noqa: T201


def print_header(title):
print
print("#", title)
print() # noqa: T201
print("#", title) # noqa: T201


def create_dope_sheet_blueprint():
Expand All @@ -93,27 +93,35 @@ def create_dope_sheet_blueprint():

print_header("Sliding forward")
intervals = SlidingPeriodicInterval(
start=yesterday, stop=tomorrow, every=timedelta(days=1)
start=yesterday,
stop=tomorrow,
every=timedelta(days=1),
)
print_intervals(intervals)

# Just reversing the list of intervals yields deterministic results as it is literally
# just the opposite of sliding forward without any different computation involved.
print_header("Sliding reverse")
intervals = SlidingPeriodicInterval(
start=yesterday, stop=tomorrow, every=timedelta(days=1)
start=yesterday,
stop=tomorrow,
every=timedelta(days=1),
)
print_intervals(reversed(list(intervals)))

print_header("Cumulative I (unaligned)")
intervals = CumulativePeriodicInterval(
start=yesterday, stop=tomorrow, every=timedelta(days=1)
start=yesterday,
stop=tomorrow,
every=timedelta(days=1),
)
print_intervals(intervals)

print_header("Cumulative II (aligned)")
now_aligned_to_hour = now - timedelta(
minutes=now.minute, seconds=now.second, microseconds=now.microsecond
minutes=now.minute,
seconds=now.second,
microseconds=now.microsecond,
)
intervals = CumulativePeriodicInterval(
start=now_aligned_to_hour,
Expand Down
Loading

0 comments on commit 415c79f

Please sign in to comment.