Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: small fixes #2

Merged
merged 1 commit into from
Apr 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
pyenv: .python-version

.python-version: setup.cfg
if [ -z "`pyenv virtualenvs | grep preset-cli`" ]; then\
pyenv virtualenv preset-cli;\
if [ -z "`pyenv virtualenvs | grep backend-sdk`" ]; then\
pyenv virtualenv backend-sdk;\
fi
if [ ! -f .python-version ]; then\
pyenv local preset-cli;\
pyenv local backend-sdk;\
fi
pip install -e '.[testing]'
touch .python-version
Expand All @@ -14,11 +14,14 @@ test: pyenv
pytest --cov=src/preset_cli -vv tests/ --doctest-modules src/preset_cli

clean:
pyenv virtualenv-delete preset-cli
pyenv virtualenv-delete backend-sdk

spellcheck:
codespell -S "*.json" src/preset_cli docs/*rst tests templates

requirements.txt: .python-version
pip install --upgrade pip
pip-compile --no-annotate

check:
pre-commit run --all-files
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ testing =
# awesome = pyscaffoldext.awesome.extension:AwesomeExtension
console_scripts =
preset-cli = preset_cli.cli.main:preset_cli
superset-cli = preset_cli.cli.superset.main.superset_cli

[tool:pytest]
# Specify command line options as you would do when invoking pytest directly.
Expand Down
56 changes: 52 additions & 4 deletions src/preset_cli/cli/superset/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""
Main entry point for Superset commands.
"""
from typing import Any

import click
from yarl import URL
Expand All @@ -24,7 +25,7 @@
help="Password (leave empty for prompt)",
)
@click.pass_context
def superset(
def superset_cli(
ctx: click.core.Context,
instance: str,
username: str = "admin",
Expand All @@ -42,6 +43,53 @@ def superset(
ctx.obj["AUTH"] = UsernamePasswordAuth(URL(instance), username, password)


superset.add_command(sql)
superset.add_command(sync)
superset.add_command(export)
superset_cli.add_command(sql)
superset_cli.add_command(sync)
superset_cli.add_command(export)


@click.group()
@click.pass_context
def superset(ctx: click.core.Context) -> None:
"""
Send commands to one or more Superset instances.
"""
ctx.ensure_object(dict)


def mutate_commands(source: click.core.Group, target: click.core.Group) -> None:
"""
Programmatically modify commands so they work with workspaces.
"""
for name, command in source.commands.items():

if isinstance(command, click.core.Group):

@click.group()
@click.pass_context
def new_group(
ctx: click.core.Context, *args: Any, command=command, **kwargs: Any
) -> None:
ctx.invoke(command, *args, **kwargs)

mutate_commands(command, new_group)
new_group.params = command.params[:]
target.add_command(new_group, name)

else:

@click.command()
@click.pass_context
def new_command(
ctx: click.core.Context, *args: Any, command=command, **kwargs: Any
) -> None:
for instance in ctx.obj["WORKSPACES"]:
click.echo(f"\n{instance}")
ctx.obj["INSTANCE"] = instance
ctx.invoke(command, *args, **kwargs)

new_command.params = command.params[:]
target.add_command(new_command, name)


mutate_commands(superset_cli, superset)
2 changes: 2 additions & 0 deletions src/preset_cli/cli/superset/sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ def run_session(
is_terminated, quote_context = get_query_termination(query)
if is_terminated:
run_query(client, database_id, query)
lines = []
quote_context = " "

click.echo("Goodbye!")

Expand Down
6 changes: 3 additions & 3 deletions tests/cli/superset/export_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from preset_cli.auth.main import Auth
from preset_cli.cli.superset.export import export_resource
from preset_cli.cli.superset.main import superset
from preset_cli.cli.superset.main import superset_cli


@pytest.fixture
Expand Down Expand Up @@ -101,7 +101,7 @@ def test_export(mocker: MockerFixture, fs: FakeFilesystem) -> None:

runner = CliRunner()
result = runner.invoke(
superset,
superset_cli,
["https://superset.example.org/", "export", "/path/to/root"],
catch_exceptions=False,
)
Expand Down Expand Up @@ -130,7 +130,7 @@ def test_export_with_custom_auth(mocker: MockerFixture, fs: FakeFilesystem) -> N

runner = CliRunner()
result = runner.invoke(
superset,
superset_cli,
["https://superset.example.org/", "export", "/path/to/root"],
catch_exceptions=False,
obj={"AUTH": Auth()},
Expand Down
131 changes: 131 additions & 0 deletions tests/cli/superset/main_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"""
Tests for the Superset dispatcher.
"""

import click
from click.testing import CliRunner

from preset_cli.cli.superset.main import mutate_commands, superset


def test_mutate_commands() -> None:
"""
Test ``mutate_commands``.
"""

@click.group()
def source_group() -> None:
"""
A simple group of commands.
"""

@click.command()
@click.argument("name")
def source_command(name: str) -> None:
"""
Say hello.
"""
click.echo(f"Hello, {name}!")

source_group.add_command(source_command)

@click.group()
def source_subgroup() -> None:
"""
A simple subgroup.
"""

@click.command()
@click.argument("name")
def source_subcommand(name: str) -> None:
"""
Say goodbye
"""
click.echo(f"Goodbye, {name}!")

source_subgroup.add_command(source_subcommand)
source_group.add_command(source_subgroup)

@click.group()
@click.pass_context
def target_group(ctx: click.core.Context) -> None:
"""
The target group to which commands will be added to.
"""
ctx.ensure_object(dict)
ctx.obj["WORKSPACES"] = ["instance1", "instance2"]

mutate_commands(source_group, target_group)

runner = CliRunner()

result = runner.invoke(
target_group,
["source-command", "Alice"],
catch_exceptions=False,
)
assert result.exit_code == 0
assert (
result.output
== """
instance1
Hello, Alice!

instance2
Hello, Alice!
"""
)

result = runner.invoke(
target_group,
["source-subgroup", "source-subcommand", "Alice"],
catch_exceptions=False,
)
assert result.exit_code == 0
assert (
result.output
== """
instance1
Goodbye, Alice!

instance2
Goodbye, Alice!
"""
)


def test_superset() -> None:
"""
Test the ``superset`` command.
"""
runner = CliRunner()

result = runner.invoke(superset, ["--help"], catch_exceptions=False)
assert result.exit_code == 0
assert (
result.output
== """Usage: superset [OPTIONS] COMMAND [ARGS]...

Send commands to one or more Superset instances.

Options:
--help Show this message and exit.

Commands:
export
sql
sync
"""
)

result = runner.invoke(superset, ["export", "--help"], catch_exceptions=False)
assert result.exit_code == 0
assert (
result.output
== """Usage: superset export [OPTIONS] DIRECTORY

Options:
--overwrite Overwrite existing resources
--help Show this message and exit.
"""
)
56 changes: 51 additions & 5 deletions tests/cli/superset/sql_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from pytest_mock import MockerFixture
from yarl import URL

from preset_cli.cli.superset.main import superset
from preset_cli.cli.superset.main import superset_cli
from preset_cli.cli.superset.sql import run_query, run_session
from preset_cli.exceptions import ErrorLevel, SupersetError

Expand Down Expand Up @@ -106,6 +106,52 @@ def test_run_session(mocker: MockerFixture, fs: FakeFilesystem) -> None:
)


def test_run_session_multiple_commands(
mocker: MockerFixture, fs: FakeFilesystem,
) -> None:
"""
Test ``run_session``.
"""
history = Path("/path/to/.config/preset-cli/")
os = mocker.patch("preset_cli.cli.superset.sql.os")
os.path.expanduser.return_value = str(history)

client = mocker.MagicMock()
client.run_query.side_effect = [
pd.DataFrame([{"answer": 42}]),
pd.DataFrame([{"question": "Life, universe, everything"}]),
]

stdout = mocker.patch("sys.stdout", new_callable=StringIO)
PromptSession = mocker.patch("preset_cli.cli.superset.sql.PromptSession")
session = PromptSession()
session.prompt.side_effect = [
"SELECT 42 AS answer;",
"SELECT 'Life, universe, everything' AS question;",
"",
EOFError(),
]

run_session(
client=client,
database_id=1,
database_name="GSheets",
url=URL("https://superset.example.org/"),
)
result = stdout.getvalue()
assert (
result
== """ answer
--------
42
question
--------------------------
Life, universe, everything
Goodbye!
"""
)


def test_run_session_multiline(mocker: MockerFixture, fs: FakeFilesystem) -> None:
"""
Test ``run_session`` with multilines.
Expand Down Expand Up @@ -224,7 +270,7 @@ def test_sql_run_query(mocker: MockerFixture) -> None:

runner = CliRunner()
result = runner.invoke(
superset,
superset_cli,
[
"https://superset.example.org/",
"sql",
Expand All @@ -251,7 +297,7 @@ def test_sql_run_session(mocker: MockerFixture) -> None:

runner = CliRunner()
result = runner.invoke(
superset,
superset_cli,
[
"https://superset.example.org/",
"sql",
Expand Down Expand Up @@ -281,7 +327,7 @@ def test_sql_run_query_no_databases(mocker: MockerFixture) -> None:

runner = CliRunner()
result = runner.invoke(
superset,
superset_cli,
[
"https://superset.example.org/",
"sql",
Expand Down Expand Up @@ -312,7 +358,7 @@ def test_sql_choose_database(mocker: MockerFixture) -> None:

runner = CliRunner()
result = runner.invoke(
superset,
superset_cli,
[
"https://superset.example.org/",
"sql",
Expand Down
Loading