Skip to content

Commit

Permalink
Add ability to run application from the command line.
Browse files Browse the repository at this point in the history
  • Loading branch information
MrCurtis committed Jan 31, 2024
1 parent 23fa1d8 commit b7ef96b
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 0 deletions.
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ classifiers = [

[project.urls]
"Homepage" = "https://github.com/MrCurtis/fk-graph"

[project.scripts]
fk-graph = "fk_graph.cli:main"
37 changes: 37 additions & 0 deletions src/fk_graph/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from argparse import ArgumentParser

from sqlalchemy import create_engine

from fk_graph import setup_data, get_graph
from fk_graph.plotly_functions import run_app

def main():
args = _parse_args()
if args.demo:
engine = create_engine("sqlite+pysqlite:///:memory:")
setup_data(engine)
elif args.connection_string:
engine = create_engine(args.connection_string)
graph = get_graph(engine, args.table, args.primary_key)
run_app(graph)

def _parse_args():
parser = ArgumentParser(
prog="fk-graph",
description="Visualise the graphs hidden within relational databases.",

)
parser.add_argument("--demo", action="store_true", help="Run with the built-in demo database.")
parser.add_argument("--connection-string")
parser.add_argument("--table", required=True)
parser.add_argument("--primary-key", required=True)
args = parser.parse_args()
if (
(not args.demo and args.connection_string is None)
or
(args.demo and args.connection_string is not None)
):
parser.error(
"Exactly one of --demo and --connection-string should be used."
)
return args
66 changes: 66 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from shlex import split as shlex_split
from subprocess import Popen, run
from time import sleep
from unittest import TestCase

from requests import get
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

import logging

logging.basicConfig(level=logging.DEBUG)

s = requests.Session()
retries = Retry(total=5, backoff_factor=1, status_forcelist=[502, 503, 504])
s.mount('http://', HTTPAdapter(max_retries=retries))
s.mount('https://', HTTPAdapter(max_retries=retries))

class TestCLI(TestCase):
def test_simple_case(self):
command = "fk-graph --demo --table=table_a --primary-key=1"
with Popen(shlex_split(command)) as process:
response = s.get("http://localhost:8050")
process.terminate()
# Because of the javascripty-nature of the app, we can
# only really inspect the status code.
self.assertEqual(response.status_code, 200)

def test_errors_if_both_demo_and_connection_string_included(self):
command = (
"fk-graph"
" --demo"
" --connection-string=\"sqlite+pysqlite:///:memory:\""
" --table=table_a"
" --primary-key=1"
)
completed_process = run(
shlex_split(command),
capture_output=True,
text=True,
timeout=5
)
self.assertEqual(completed_process.returncode, 2)
self.assertIn(
"Exactly one of --demo and --connection-string should be used.",
completed_process.stderr
)

def test_errors_if_neither_demo_or_connection_string_included(self):
command = (
"fk-graph"
" --table=table_a"
" --primary-key=1"
)
completed_process = run(
shlex_split(command),
capture_output=True,
text=True,
timeout=5
)
self.assertEqual(completed_process.returncode, 2)
self.assertIn(
"Exactly one of --demo and --connection-string should be used.",
completed_process.stderr
)

0 comments on commit b7ef96b

Please sign in to comment.