Skip to content

Commit

Permalink
refactor: extract CLI into separate package (#23)
Browse files Browse the repository at this point in the history
### Summary of Changes

Move the CLI out of the `server` package.
  • Loading branch information
lars-reimann authored Dec 4, 2023
1 parent 613589b commit 20e9aac
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 27 deletions.
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ pip install safe-ds-runner

## Usage

Launch the runner:
Start the runner server:

```shell
safe-ds-runner
safe-ds-runner start
```

## Documentation
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ packages = [
]

[tool.poetry.scripts]
safe-ds-runner = "safeds_runner.server.main:main"
safe-ds-runner = "safeds_runner.main:main"

[tool.poetry.dependencies]
python = "^3.11,<3.13"
Expand Down
5 changes: 5 additions & 0 deletions src/safeds_runner/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""The command line interface of the application."""

from ._cli import cli

__all__ = ["cli"]
47 changes: 47 additions & 0 deletions src/safeds_runner/cli/_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import argparse
import logging
from importlib.metadata import version

from safeds_runner.server.main import start_server


class Commands:
START = "start"


def cli() -> None: # pragma: no cover
"""Run the application via the command line."""
args = _get_args()

# Set logging level
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
else:
logging.basicConfig(level=logging.INFO)

# Run command
match args.command:
case Commands.START:
start_server(args.port)


def _get_args() -> argparse.Namespace: # pragma: no cover
parser = argparse.ArgumentParser(description="Execute Safe-DS programs that were compiled to Python.")
parser.add_argument(
"-V",
"--version",
action="version",
version=f"%(prog)s {version('safe-ds-runner')}",
)
parser.add_argument("-v", "--verbose", help="increase logging verbosity", action="store_true")

# Commands
subparsers = parser.add_subparsers(dest="command")
_add_start_subparser(subparsers)

return parser.parse_args()


def _add_start_subparser(subparsers: argparse._SubParsersAction) -> None: # pragma: no cover
parser = subparsers.add_parser(Commands.START, help="start the Safe-DS Runner server")
parser.add_argument("-p", "--port", type=int, default=5000, help="the port to use")
8 changes: 8 additions & 0 deletions src/safeds_runner/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
"""The main entry point of the application."""

from safeds_runner.cli import cli


def main() -> None: # pragma: no cover
"""Run the application."""
cli()
27 changes: 4 additions & 23 deletions src/safeds_runner/server/main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
"""Module containing the main entry point, for starting the Safe-DS runner."""

import argparse
import json
import logging
from importlib.metadata import version

import flask.app
import flask_sock
Expand Down Expand Up @@ -162,12 +160,8 @@ def send_websocket_message(connection: simple_websocket.Server, message: Message
connection.send(json.dumps(message.to_dict()))


def main() -> None: # pragma: no cover
"""
Execute the runner application.
Main entry point of the runner application.
"""
def start_server(port: int) -> None: # pragma: no cover
"""Start the Safe-DS Runner server."""
# Allow prints to be unbuffered by default
import builtins
import functools
Expand All @@ -177,19 +171,6 @@ def main() -> None: # pragma: no cover
logging.getLogger().setLevel(logging.DEBUG)
from gevent.pywsgi import WSGIServer

parser = argparse.ArgumentParser(description="Start Safe-DS Runner on a specific port.")
parser.add_argument("--port", type=int, default=5000, help="Port on which to run the python server.")
parser.add_argument(
"-V",
"--version",
action="version",
version="%(prog)s {version}".format(version=version("safe-ds-runner")),
)
args = parser.parse_args()
logging.info("Starting Safe-DS Runner on port %s", str(args.port))
logging.info("Starting Safe-DS Runner on port %s", str(port))
# Only bind to host=127.0.0.1. Connections from other devices should not be accepted
WSGIServer(("127.0.0.1", args.port), app).serve_forever()


if __name__ == "__main__":
main() # pragma: no cover
WSGIServer(("127.0.0.1", port), app).serve_forever()
2 changes: 1 addition & 1 deletion tests/safeds_runner/server/test_runner_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


def test_should_runner_start_successfully() -> None:
process = subprocess.Popen(["poetry", "run", "safe-ds-runner"], cwd=_project_root, stderr=subprocess.PIPE)
process = subprocess.Popen(["poetry", "run", "safe-ds-runner", "start"], cwd=_project_root, stderr=subprocess.PIPE)
while process.poll() is None:
process_line = str(typing.cast(IO[bytes], process.stderr).readline(), "utf-8").strip()
# Wait for first line of log
Expand Down

0 comments on commit 20e9aac

Please sign in to comment.