Skip to content

Commit

Permalink
Merge branch '0.7' of github.com:msqd/harp into 0.7
Browse files Browse the repository at this point in the history
  • Loading branch information
hartym committed Nov 14, 2024
2 parents 0ec4218 + 937a7f4 commit b6e1a16
Show file tree
Hide file tree
Showing 18 changed files with 214 additions and 144 deletions.
64 changes: 0 additions & 64 deletions .github/workflows/documentation.yml

This file was deleted.

1 change: 1 addition & 0 deletions docs/changelogs/unreleased.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ Unreleased
Fixed
:::::

* DX: Add the ability to use --set x=y or --set x y (both equivalent) to all commands (@masterivanic, #590)
* UI: Correctly display header values containing a semicolon character (#577, @ArthurD1)
5 changes: 2 additions & 3 deletions harp/commandline/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
from rich.syntax import Syntax
from rich.tree import Tree

from harp.commandline.options.server import CommonServerOptions, add_harp_server_click_options
from harp.commandline.options.server import CommonServerOptions, server_command
from harp.config import ConfigurationBuilder
from harp.config.asdict import asdict
from harp.utils.commandline import click


@click.command("config", short_help="Prints the current configuration.")
@add_harp_server_click_options
@server_command("config", short_help="Prints the current configuration.")
@click.option("--raw", is_flag=True, help="Prints the raw configuration as a dictionary.")
@click.option("--json", is_flag=True, help="Prints the raw configuration as JSON.")
@click.option(
Expand Down
2 changes: 1 addition & 1 deletion harp/commandline/cookiecutters/project/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 {{cookiecutter.author}}
Copyright (c) 2024 {{cookiecutter.author_name}} <{{cookiecutter.author_email}}>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
12 changes: 10 additions & 2 deletions harp/commandline/cookiecutters/project/cookiecutter.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@
"name": "HARP Project",
"__dir_name": "{{cookiecutter.name | slugify}}",
"__pkg_name": "{{cookiecutter.name | slugify(separator='_')}}",
"author": "Smart Anonymous Harpist",
"author_name": "Smart Anonymous Harpist",
"author_email": "[email protected]",
"create_application": false,
"create_config": true
"create_config": true,
"__prompts__": {
"name": "Project name",
"author_name": "Author name",
"author_email": "Author email",
"create_application": "Create application folder ?",
"create_config": "Create config file ?"
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
#! /bin/bash

if [ "{{cookiecutter.create_application}}" == "False" ]; then
echo "Removing application folder (create_application == False)."
rm -rf ./{{cookiecutter.__pkg_name}}
fi


if [ "{{cookiecutter.create_config}}" == "False" ]; then
echo "Removing config file (create_config == False)."
rm -f ./config.yml
fi

echo "Congratulations, your HARP project «{{cookiecutter.name}}» has been created in «{{cookiecutter.__dir_name}}»."
echo
echo "To install the project dependencies, run '(cd {{cookiecutter.__dir_name}} && make install)'."
echo "To run the tests, run '(cd {{cookiecutter.__dir_name}} && make test)'."
echo "To start your project, run '(cd {{cookiecutter.__dir_name}} && make)'."
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
name = "{{cookiecutter.__pkg_name}}"
version = "0.1.0"
description = ""
authors = ["{{cookiecutter.author}}"]
authors = [
"{{cookiecutter.author_name}} <{{cookiecutter.author_email}}>",
]
readme = "README.rst"
{% if not cookiecutter.create_application -%}
package-mode = false
{%- endif %}

[tool.poetry.dependencies]
python = "^3.12"
harp-proxy = "*"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
5 changes: 4 additions & 1 deletion harp/commandline/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ def create(template):
"""Creates a new project using cookiecutter."""

if not check_packages("cookiecutter"):
raise click.UsageError("You need to install cookiecutter to use this command (or use the harp[dev] extra).")
raise click.UsageError(
"You need to install cookiecutter to use this command (or use the `dev` extra, for example using "
"`pip install harp-proxy[dev]` or `poetry install -E dev`)."
)

from cookiecutter.main import cookiecutter

Expand Down
20 changes: 7 additions & 13 deletions harp/commandline/migrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from sqlalchemy.ext.asyncio import create_async_engine

from harp import get_logger
from harp.commandline.options.server import add_harp_server_click_options
from harp.commandline.options.server import server_command
from harp.utils.commandline import click
from harp_apps.storage.utils.migrations import (
create_alembic_config,
Expand All @@ -21,8 +21,7 @@
logger = get_logger(__name__)


@click.command("db:migrate")
@add_harp_server_click_options
@server_command("db:migrate")
@click.argument("operation", nargs=1, type=click.Choice(["up", "down"]))
@click.argument("revision", nargs=1)
@click.option("--reset", is_flag=True, help="Reset the database (drop all before migrations).")
Expand All @@ -44,8 +43,7 @@ def migrate(*, operation, revision, reset=False, **kwargs):
migrate = cast(BaseCommand, migrate)


@click.command("db:create-migration")
@add_harp_server_click_options
@server_command("db:create-migration")
@click.argument("message", nargs=1)
def create_migration(*, message, **kwargs):
settings = create_harp_settings_with_storage_from_command_line_options(kwargs)
Expand All @@ -56,8 +54,7 @@ def create_migration(*, message, **kwargs):
create_migration = cast(BaseCommand, create_migration)


@click.command("db:merge")
@add_harp_server_click_options
@server_command("db:merge")
@click.argument("message", nargs=1)
@click.argument("revisions", nargs=-1)
def run_db_merge_command(*, message, revisions, **kwargs):
Expand All @@ -69,10 +66,9 @@ def run_db_merge_command(*, message, revisions, **kwargs):
run_db_merge_command = cast(BaseCommand, run_db_merge_command)


@click.command("db:feature")
@server_command("db:feature")
@click.argument("operation", nargs=1, type=click.Choice(["add", "remove"]))
@click.argument("features", nargs=-1)
@add_harp_server_click_options
def feature(features, operation, **kwargs):
settings = create_harp_settings_with_storage_from_command_line_options(kwargs)
alembic_cfg = create_alembic_config(settings.get("storage").url)
Expand All @@ -96,8 +92,7 @@ def feature(features, operation, **kwargs):
feature = cast(BaseCommand, feature)


@click.command("db:history")
@add_harp_server_click_options
@server_command("db:history")
def history(**kwargs):
settings = create_harp_settings_with_storage_from_command_line_options(kwargs)
alembic_cfg = create_alembic_config(settings.get("storage").url)
Expand All @@ -107,8 +102,7 @@ def history(**kwargs):
history = cast(BaseCommand, history)


@click.command("db:reset")
@add_harp_server_click_options
@server_command("db:reset")
def reset(**kwargs):
settings = create_harp_settings_with_storage_from_command_line_options(kwargs)
alembic_cfg = create_alembic_config(settings.get("storage").url)
Expand Down
76 changes: 69 additions & 7 deletions harp/commandline/options/server.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from dataclasses import dataclass, field
from itertools import chain
from shlex import quote
from typing import Iterable
from typing import Any, Callable, Iterable, List, Optional, Type, Union

from click import Command
from click.decorators import CmdType

from harp.utils.commandline import click, code

Expand All @@ -16,8 +19,8 @@ def __post_init__(self):
self.options = dict(map(lambda x: x.split("=", 1), self.options))


def _parse_option(x):
key, value = x.split("=", 1)
def _parse_option(option: tuple[str, str]) -> tuple[str, Union[str, bool]]:
key, value = option
if value == "true":
value = True
elif value == "false":
Expand Down Expand Up @@ -57,7 +60,7 @@ def __post_init__(self):
self.endpoints = dict(map(lambda x: x.split("=", 1), self.endpoints))


def add_harp_config_options(f):
def _config_click_options(f):
"""
Decorate a click command to add configuration options, in the right order.
"""
Expand All @@ -83,7 +86,8 @@ def add_harp_config_options(f):
"--set",
"options",
multiple=True,
help=f"Add configuration options (e.g. {code('--set foo=bar')}, can be used multiple times).",
type=(str, str),
help=f"Add configuration options (e.g. {code('--set foo=bar')} or {code('--set foo bar')}, can be used multiple times).",
),
]

Expand All @@ -95,7 +99,7 @@ def add_harp_config_options(f):
return f


def add_harp_server_click_options(f):
def _server_click_options(f):
"""
Decorate a click command to add common server options, in the right order.
"""
Expand Down Expand Up @@ -123,6 +127,64 @@ def add_harp_server_click_options(f):
for option in reversed(options):
f = option(f)

f = add_harp_config_options(f)
f = _config_click_options(f)

return f


class _EnhancedParserCommand(click.Command):
"""
This class override parse_args click function parse args enter in cli when type command with space or = for --set
command:
eg: --set arg=value or arg value
"""

def parse_args(self, ctx: click.Context, args: List[str]) -> List[str]:
index = 0
while index < len(args):
if args[index] == "--set":
if index + 1 < len(args):
# if an equal sign is present, we expand the argument into two separated arguments
if "=" in args[index + 1]:
args = args[: index + 1] + args[index + 1].split("=") + args[index + 2 :]
index += 1
index += 1
return super().parse_args(ctx, args)


def server_command(
name: Union[Optional[str], Callable[..., Any]] = None,
cls: Type[CmdType] = _EnhancedParserCommand,
**attrs: Any,
) -> Union[Command, Callable[[Callable[..., Any]], Union[Command, CmdType]]]:
"""
Creates a click command with server options (--enable, --disable, --applications, --endpoint and all configuration
options).
"""

def decorator(f: [Callable[..., Any]]) -> CmdType:
command_decorator = click.command(name=name, cls=cls, **attrs)
f = _server_click_options(f)
f = command_decorator(f)
return f

return decorator


def config_command(
name: Union[Optional[str], Callable[..., Any]] = None,
cls: Type[CmdType] = _EnhancedParserCommand,
**attrs: Any,
) -> Union[Command, Callable[[Callable[..., Any]], Union[Command, CmdType]]]:
"""
Creates a click command with configuration options (--set, --example, --file).
"""

def decorator(f: [Callable[..., Any]]) -> CmdType:
command_decorator = click.command(name=name, cls=cls, **attrs)
f = _config_click_options(f)
f = command_decorator(f)
return f

return decorator
6 changes: 2 additions & 4 deletions harp/commandline/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@
from click import BaseCommand

from harp import run
from harp.commandline.options.server import CommonServerOptions, add_harp_server_click_options
from harp.commandline.options.server import CommonServerOptions, server_command
from harp.config import ConfigurationBuilder
from harp.settings import USE_PROMETHEUS
from harp.utils.commandline import click


@click.command(
@server_command(
short_help="Starts HARP server.",
help="""Starts HARP server, using the provided configuration. This is the main process and will be the only process
you need on a live server, it will serve both the proxy ports and the compiled frontend assets (dashboard).""",
)
@add_harp_server_click_options
def server(**kwargs):
_info = None
if USE_PROMETHEUS:
Expand Down
Loading

0 comments on commit b6e1a16

Please sign in to comment.