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

Shell completion #976

Merged
merged 4 commits into from
Feb 5, 2024
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
13 changes: 1 addition & 12 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions pontos/changelog/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from pathlib import Path
from typing import NoReturn, Optional, Sequence

import shtab

from pontos.changelog.conventional_commits import ChangelogBuilder
from pontos.errors import PontosError
from pontos.terminal.null import NullTerminal
Expand All @@ -26,14 +28,15 @@ def parse_args(args: Optional[Sequence[str]] = None) -> Namespace:
" text from conventional commits between the current and next release.",
prog="pontos-changelog",
)
shtab.add_argument_to(parser)

parser.add_argument(
"--config",
"-C",
type=Path,
help="Optional. Conventional commits config file (toml), including "
"conventions. If not provided defaults are used.",
)
).complete = shtab.FILE # type: ignore[attr-defined]

parser.add_argument(
"--project",
Expand Down Expand Up @@ -83,7 +86,7 @@ def parse_args(args: Optional[Sequence[str]] = None) -> Namespace:
"-o",
type=Path,
help="Write changelog to this file.",
)
).complete = shtab.FILE # type: ignore[attr-defined]

parser.add_argument(
"--quiet",
Expand Down
53 changes: 53 additions & 0 deletions pontos/enum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SPDX-FileCopyrightText: 2024 Greenbone AG
#
# SPDX-License-Identifier: GPL-3.0-or-later

from argparse import ArgumentTypeError
from enum import Enum
from typing import Callable, Type, TypeVar, Union


class StrEnum(str, Enum):
# Should be replaced by enum.StrEnum when we require Python >= 3.11
"""
An Enum that provides str like behavior
"""

def __str__(self) -> str:
return self.value


def enum_choice(enum: Type[Enum]) -> list[str]:
"""
Return a sequence of choices for argparse from an enum
"""
return [str(e) for e in enum]


def to_choices(enum: Type[Enum]) -> str:
"""
Convert an enum to a comma separated string of choices. For example useful
in help messages for argparse.
"""
return ", ".join([str(t) for t in enum])


T = TypeVar("T", bound=Enum)


def enum_type(enum: Type[T]) -> Callable[[Union[str, T]], T]:
"""
Create a argparse type function for converting the string input into an Enum
"""

def convert(value: Union[str, T]) -> T:
if isinstance(value, str):
try:
return enum(value)
except ValueError:
raise ArgumentTypeError(
f"invalid value {value}. Expected one of {to_choices(enum)}."
) from None
return value

return convert
62 changes: 32 additions & 30 deletions pontos/github/argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
from pathlib import Path
from typing import List, Optional

import shtab

from pontos.enum import enum_choice, enum_type
from pontos.github.cmds import (
create_pull_request,
create_release,
Expand All @@ -32,25 +35,20 @@ def from_env(name: str) -> str:
return os.environ.get(name, name)


def get_repository_type(rtype: str) -> RepositoryType:
return RepositoryType[rtype]


def parse_args(
args: Optional[List[str]] = None,
) -> Namespace:
"""
Parsing args for Pontos GitHub

Arguments:
args The program arguments passed by exec
term The terminal to print
args The program arguments passed by exec
"""

parser = ArgumentParser(
description="Greenbone GitHub API.",
)

shtab.add_argument_to(parser)
parser.add_argument(
"--quiet",
"-q",
Expand All @@ -62,20 +60,21 @@ def parse_args(
"--log-file",
dest="log_file",
type=str,
help="Acivate logging using the given file path",
)
help="Activate logging using the given file path",
).complete = shtab.FILE # type: ignore[attr-defined]

subparsers = parser.add_subparsers(
title="subcommands",
description="valid subcommands",
required=True,
help="additional help",
description="Valid subcommands",
help="Additional help",
dest="command",
)

# create a PR from command line
pr_parser = subparsers.add_parser(
"pull-request", aliases=["pr", "PR", "pullrequest"]
"pull-request",
aliases=["pr", "PR", "pullrequest"],
help="Pull request related commands",
)

pr_parser.set_defaults(func=pull_request)
Expand All @@ -95,8 +94,8 @@ def parse_args(
title="method",
dest="pr_method",
metavar="name",
description="valid pull request method",
help="pull request method",
description="Valid pull request method",
help="Pull request method",
required=True,
)

Expand Down Expand Up @@ -136,7 +135,7 @@ def parse_args(
)

update_pr_parser = pr_subparsers.add_parser(
"update", help="update Pull Request"
"update", help="Update Pull Request"
)

update_pr_parser.set_defaults(pr_func=update_pull_request)
Expand Down Expand Up @@ -166,7 +165,7 @@ def parse_args(

# get files
file_status_parser = subparsers.add_parser(
"file-status", aliases=["status", "FS"]
"file-status", aliases=["status", "FS"], help="File status"
)

file_status_parser.set_defaults(func=file_status)
Expand All @@ -182,7 +181,7 @@ def parse_args(
file_status_parser.add_argument(
"-s",
"--status",
choices=FileStatus,
choices=enum_choice(FileStatus),
default=[FileStatus.ADDED, FileStatus.MODIFIED],
nargs="+",
help="What file status should be returned. Default: %(default)s",
Expand Down Expand Up @@ -212,7 +211,9 @@ def parse_args(
)

# labels
label_parser = subparsers.add_parser("labels", aliases=["L"])
label_parser = subparsers.add_parser(
"labels", aliases=["L"], help="Issue/pull Request label handling"
)

label_parser.set_defaults(func=labels)

Expand Down Expand Up @@ -243,7 +244,9 @@ def parse_args(
)

# orga-repos
repos_parser = subparsers.add_parser("repos", aliases=["R"])
repos_parser = subparsers.add_parser(
"repos", aliases=["R"], help="Repository information"
)

repos_parser.set_defaults(func=repos)

Expand All @@ -262,8 +265,8 @@ def parse_args(

repos_parser.add_argument(
"--type",
choices=RepositoryType,
type=get_repository_type,
choices=enum_choice(RepositoryType),
type=enum_type(RepositoryType),
default=RepositoryType.PUBLIC,
help=(
"Define the type of repositories that should be covered. "
Expand All @@ -279,7 +282,7 @@ def parse_args(

# create a release from command line
re_parser = subparsers.add_parser(
"release", aliases=["re", "RE", "release"]
"release", aliases=["re", "RE", "release"], help="Release commands"
)

re_parser.set_defaults(func=release)
Expand All @@ -299,7 +302,7 @@ def parse_args(
title="method",
dest="re_method",
metavar="name",
description="valid release method",
description="Valid release method",
help="Release method",
required=True,
)
Expand Down Expand Up @@ -353,7 +356,9 @@ def parse_args(
)

# Create a tag from command line
tag_parser = subparsers.add_parser("tag", aliases=["tag", "TAG"])
tag_parser = subparsers.add_parser(
"tag", aliases=["tag", "TAG"], help="Tag commands"
)

tag_parser.set_defaults(func=tag)

Expand All @@ -372,7 +377,7 @@ def parse_args(
title="method",
dest="tag_method",
metavar="name",
description="valid tag method",
description="Valid tag method",
help="Release method",
required=True,
)
Expand Down Expand Up @@ -425,7 +430,4 @@ def parse_args(
" YYYY-MM-DDTHH:MM:SSZ."
),
)

parsed_args = parser.parse_args(args)

return parsed_args
return parser.parse_args(args)
2 changes: 1 addition & 1 deletion pontos/github/cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ async def repos(terminal: Terminal, args: Namespace):
exists = await api.organizations.exists(args.orga)
if not exists:
terminal.error(
f"PR {args.orga} is not existing or authorisation failed."
f"Organization {args.orga} is not existing or authorisation failed."
)
sys.exit(1)

Expand Down
1 change: 1 addition & 0 deletions pontos/github/script/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def main():
child_parser = ArgumentParser(parents=[parser])
run_add_arguments_function(module, child_parser)
args = child_parser.parse_args()

token = args.token
timeout = args.timeout

Expand Down
3 changes: 3 additions & 0 deletions pontos/github/script/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import os
from argparse import ArgumentParser

import shtab

from pontos.github.api.helper import DEFAULT_TIMEOUT

GITHUB_TOKEN = "GITHUB_TOKEN"
Expand All @@ -19,6 +21,7 @@ def create_parser() -> ArgumentParser:
A new ArgumentParser instance add the default arguments
"""
parser = ArgumentParser(add_help=False)
shtab.add_argument_to(parser)
parser.add_argument(
"--token",
default=os.environ.get(GITHUB_TOKEN),
Expand Down
12 changes: 1 addition & 11 deletions pontos/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@

from dataclasses import dataclass
from datetime import date, datetime, timezone
from enum import Enum
from inspect import isclass
from typing import Any, Dict, Type, Union, get_args, get_origin, get_type_hints

from dateutil import parser as dateparser

from pontos.enum import StrEnum
from pontos.errors import PontosError

__all__ = (
Expand All @@ -27,16 +27,6 @@ class ModelError(PontosError):
"""


class StrEnum(str, Enum):
# Should be replaced by enum.StrEnum when we require Python >= 3.11
"""
An Enum that provides str like behavior
"""

def __str__(self) -> str:
return self.value


def dotted_attributes(obj: Any, data: Dict[str, Any]) -> Any:
"""
Set dotted attributes on an object
Expand Down
Loading
Loading