Skip to content

Commit

Permalink
refactor: Fix boolean traps in signatures (#287)
Browse files Browse the repository at this point in the history
  • Loading branch information
pederhan authored Jan 21, 2025
1 parent 2080fc0 commit dc1650c
Show file tree
Hide file tree
Showing 30 changed files with 108 additions and 84 deletions.
2 changes: 1 addition & 1 deletion docs/scripts/utils/markup.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def symbol(self) -> str:
return s

@classmethod
def from_span(cls, span: MarkdownSpan, end: bool = False) -> MarkdownSymbol:
def from_span(cls, span: MarkdownSpan, *, end: bool = False) -> MarkdownSymbol:
return cls(
position=span.end if end else span.start,
italic=span.italic,
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ extend-select = [
"C4", # flake8-comprehensions
"B", # flake8-bugbear
"UP", # pyupgrade
"FBT002", # flake8-boolean-trap (Positional bool values with defaults)
]
ignore = [
"E501", # Avoid enforcing line-length violations
Expand Down
7 changes: 6 additions & 1 deletion tests/pyzabbix/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,12 @@ def test_client_logout(httpserver: HTTPServer, auth_type: AuthType, auth: str) -

# We only expect a logout request if we are using a sessionid and have an auth token
if auth_type == "sessionid" and auth:
add_zabbix_endpoint(httpserver, "user.logout", {}, True)
add_zabbix_endpoint(
httpserver,
"user.logout",
params={},
response=True, # the value `True` as the response
)
zabbix_client = ZabbixAPI(server=httpserver.url_for("/api_jsonrpc.php"))
zabbix_client.auth = auth
if auth_type == "token":
Expand Down
1 change: 1 addition & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
def add_zabbix_endpoint(
httpserver: HTTPServer,
method: str, # method is zabbix API method, not HTTP method
*,
params: dict[str, Any],
response: Json,
auth: Optional[str] = None,
Expand Down
2 changes: 1 addition & 1 deletion zabbix_cli/_patches/typer.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ def patch__get_rich_console() -> None:
)
TYPER_THEME = Theme(styles)

def _get_rich_console(stderr: bool = False) -> Console:
def _get_rich_console(stderr: bool = False) -> Console: # noqa: FBT002
return Console(
theme=TYPER_THEME,
highlighter=highlighter,
Expand Down
15 changes: 9 additions & 6 deletions zabbix_cli/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ def set_user_session(self, url: str, username: str, session_id: str) -> None:
self.set_sessions(url, session)

@classmethod
def load(cls, file: Path, allow_insecure: bool = False) -> SessionFile:
def load(cls, file: Path, *, allow_insecure: bool = False) -> SessionFile:
"""Load the contents of a session file."""
if not file.exists():
raise SessionFileNotFoundError("Session file does not exist: %s", file)
Expand All @@ -143,7 +143,9 @@ def load(cls, file: Path, allow_insecure: bool = False) -> SessionFile:
except Exception as e:
raise SessionFileError(f"Unable to load session file {file}: {e}") from e

def save(self, path: Optional[Path] = None, allow_insecure: bool = False) -> None:
def save(
self, path: Optional[Path] = None, *, allow_insecure: bool = False
) -> None:
path = path or self._path
if not path:
raise SessionFileError("Cannot save session file without a path.")
Expand Down Expand Up @@ -264,13 +266,13 @@ def login_with_any(self) -> tuple[ZabbixAPI, LoginInfo]:
)

def _iter_all_credentials(
self, prompt_password: bool = True
self, *, prompt_password: bool = True
) -> Generator[Credentials, None, None]:
"""Generator that yields credentials from all possible sources.
"""Generator of credentials from all possible sources.
Only yields non-empty credentials, but does not check if they are valid.
Finally yields a prompt for username and password if `prompt_password` is True.
Finally yields a prompt for username and password if `prompt_password=True`.
"""
for func in [
self._get_auth_token_env,
Expand Down Expand Up @@ -455,7 +457,7 @@ def _update_config(self, credentials: Credentials) -> None:
):
self.config.api.auth_token = SecretStr(credentials.auth_token)

def get_zabbix_url(self, prompt: bool = True) -> str:
def get_zabbix_url(self, *, prompt: bool = True) -> str:
"""Get the URL of the Zabbix server from env, config, then finally prompt for it.."""
for source in [self._get_zabbix_url_env, self._get_zabbix_url_config]:
url = source()
Expand Down Expand Up @@ -697,6 +699,7 @@ def write_auth_token_file(
username: str,
auth_token: str,
file: Path = AUTH_TOKEN_FILE,
*,
allow_insecure: bool = False,
) -> Path:
"""Write a username/auth token pair to the auth token file."""
Expand Down
2 changes: 1 addition & 1 deletion zabbix_cli/commands/results/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def config_path_str(self) -> str:
)

@classmethod
def from_debug_data(cls, state: State, with_auth: bool = False) -> DebugInfo:
def from_debug_data(cls, state: State, *, with_auth: bool = False) -> DebugInfo:
# So far we only use state, but we can expand this in the future
from zabbix_cli.exceptions import ZabbixCLIError

Expand Down
2 changes: 1 addition & 1 deletion zabbix_cli/commands/results/proxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class ShowProxiesResult(TableRenderable):
show_hosts: bool = Field(default=False, exclude=True)

@classmethod
def from_result(cls, proxy: Proxy, show_hosts: bool = False) -> Self:
def from_result(cls, proxy: Proxy, *, show_hosts: bool = False) -> Self:
return cls(proxy=proxy, show_hosts=show_hosts)

@property
Expand Down
12 changes: 6 additions & 6 deletions zabbix_cli/commands/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ def link_template_to_host(
from zabbix_cli.models import AggregateResult

templates = parse_templates_arg(
app, template_names_or_ids, strict, select_hosts=True
app, template_names_or_ids, strict=strict, select_hosts=True
)
hosts = parse_hosts_arg(app, hostnames_or_ids, strict)
hosts = parse_hosts_arg(app, hostnames_or_ids, strict=strict)
if not dryrun:
with app.state.console.status("Linking templates..."):
app.state.client.link_templates_to_hosts(templates, hosts)
Expand Down Expand Up @@ -280,9 +280,9 @@ def unlink_template_from_host(
from zabbix_cli.models import AggregateResult

templates = parse_templates_arg(
app, template_names_or_ids, strict, select_hosts=True
app, template_names_or_ids, strict=strict, select_hosts=True
)
hosts = parse_hosts_arg(app, hostnames_or_ids, strict)
hosts = parse_hosts_arg(app, hostnames_or_ids, strict=strict)

action = "Unlink and clear" if clear else "Unlink"
if not dryrun:
Expand Down Expand Up @@ -362,8 +362,8 @@ def unlink_template_from_template(
"""
from zabbix_cli.commands.results.template import LinkTemplateResult

source_templates = parse_templates_arg(app, source, strict)
dest_templates = parse_templates_arg(app, dest, strict)
source_templates = parse_templates_arg(app, source, strict=strict)
dest_templates = parse_templates_arg(app, dest, strict=strict)
if not dryrun:
with app.state.console.status("Unlinking templates..."):
app.state.client.unlink_templates(
Expand Down
6 changes: 3 additions & 3 deletions zabbix_cli/commands/templategroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ def add_template_to_group(

groups: Union[list[HostGroup], list[TemplateGroup]]
if app.state.client.version.release >= (6, 2, 0):
groups = parse_templategroups_arg(app, group_names_or_ids, strict)
groups = parse_templategroups_arg(app, group_names_or_ids, strict=strict)
else:
groups = parse_hostgroups_arg(app, group_names_or_ids, strict)
groups = parse_hostgroups_arg(app, group_names_or_ids, strict=strict)

templates = parse_templates_arg(app, template_names_or_ids, strict)
templates = parse_templates_arg(app, template_names_or_ids, strict=strict)

with app.state.console.status("Adding templates..."):
app.state.client.link_templates_to_groups(templates, groups)
Expand Down
6 changes: 4 additions & 2 deletions zabbix_cli/config/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ def set(self, key: str, value: Any) -> None:
class PluginsConfig(RootModel[dict[str, PluginConfig]]):
root: dict[str, PluginConfig] = Field(default_factory=dict)

def get(self, key: str, strict: bool = False) -> Optional[PluginConfig]:
def get(self, key: str, *, strict: bool = False) -> Optional[PluginConfig]:
"""Get a plugin configuration by name."""
conf = self.root.get(key)
if conf is None and strict:
Expand Down Expand Up @@ -614,7 +614,9 @@ def sample_config(cls) -> Config:
return cls(api=APIConfig(url="https://zabbix.example.com"), sample=True)

@classmethod
def from_file(cls, filename: Optional[Path] = None, init: bool = False) -> Config:
def from_file(
cls, filename: Optional[Path] = None, *, init: bool = False
) -> Config:
"""Load configuration from a file.
Attempts to find a config file to load if none is specified.
Expand Down
7 changes: 5 additions & 2 deletions zabbix_cli/config/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def find_config(
return None


def get_config(filename: Optional[Path] = None, init: bool = False) -> Config:
def get_config(filename: Optional[Path] = None, *, init: bool = False) -> Config:
"""Get a configuration object.
Args:
Expand Down Expand Up @@ -187,6 +187,7 @@ class DeprecatedField(NamedTuple):
def init_config(
config: Optional[Config] = None,
config_file: Optional[Path] = None,
*,
overwrite: bool = False,
# Compatibility with V2 zabbix-cli-init args
url: Optional[str] = None,
Expand Down Expand Up @@ -215,7 +216,9 @@ def init_config(
if not config:
config = Config.sample_config()
if not url:
url = str_prompt("Zabbix URL (without /api_jsonrpc.php)", url or config.api.url)
url = str_prompt(
"Zabbix URL (without /api_jsonrpc.php)", default=url or config.api.url
)
config.api.url = url

# Add username if provided
Expand Down
1 change: 1 addition & 0 deletions zabbix_cli/output/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ def warning(message: str, icon: str = Icon.WARNING, **kwargs: Any) -> None:
def error(
message: str,
icon: str = Icon.ERROR,
*,
exc_info: bool = False,
log: bool = True,
**kwargs: Any,
Expand Down
2 changes: 1 addition & 1 deletion zabbix_cli/output/formatting/bytes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from .constants import NONE_STR


def bytesize_str(b: int | None, decimal: bool = False) -> str:
def bytesize_str(b: int | None, *, decimal: bool = False) -> str:
if b is None or b < 0:
return NONE_STR
return ByteSize(b).human_readable(decimal=decimal)
38 changes: 0 additions & 38 deletions zabbix_cli/output/formatting/dates.py

This file was deleted.

2 changes: 1 addition & 1 deletion zabbix_cli/output/formatting/grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def _pluralize_word(word: str, count: int) -> str:
return word + "s"


def pluralize(word: str, count: int, with_count: bool = True) -> str:
def pluralize(word: str, count: int, *, with_count: bool = True) -> str:
"""Pluralize a word based on a count.
Examples:
Expand Down
2 changes: 1 addition & 1 deletion zabbix_cli/output/formatting/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pathlib import Path


def path_link(path: Path, absolute: bool = True) -> str:
def path_link(path: Path, *, absolute: bool = True) -> str:
"""Return a link to a path."""
abspath = path.resolve().absolute()
if absolute:
Expand Down
10 changes: 10 additions & 0 deletions zabbix_cli/output/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ def prompt_msg(*msgs: str) -> str:
@no_headless
def str_prompt(
prompt: str,
*,
default: str = ..., # pyright: ignore[reportArgumentType] # rich uses ... to signify no default
password: bool = False,
show_default: bool = True,
Expand Down Expand Up @@ -158,6 +159,7 @@ def str_prompt(
@no_headless
def str_prompt_optional(
prompt: str,
*,
default: str = "",
password: bool = False,
show_default: bool = False,
Expand All @@ -184,6 +186,7 @@ def str_prompt_optional(
@no_headless
def list_prompt(
prompt: str,
*,
empty_ok: bool = True,
strip: bool = True,
keep_empty: bool = False,
Expand All @@ -208,6 +211,7 @@ def list_prompt(
@no_headless
def int_prompt(
prompt: str,
*,
default: int | None = None,
show_default: bool = True,
min: int | None = None,
Expand All @@ -230,6 +234,7 @@ def int_prompt(
@no_headless
def float_prompt(
prompt: str,
*,
default: float | None = None,
show_default: bool = True,
min: float | None = None,
Expand All @@ -256,6 +261,7 @@ def float_prompt(
def _number_prompt(
prompt_type: type[IntPrompt],
prompt: str,
*,
default: int | float | None = ...,
show_default: bool = ...,
min: int | float | None = ...,
Expand All @@ -269,6 +275,7 @@ def _number_prompt(
def _number_prompt(
prompt_type: type[FloatPrompt],
prompt: str,
*,
default: int | float | None = ...,
show_default: bool = ...,
min: int | float | None = ...,
Expand All @@ -281,6 +288,7 @@ def _number_prompt(
def _number_prompt(
prompt_type: type[IntPrompt] | type[FloatPrompt],
prompt: str,
*,
default: int | float | None = None,
show_default: bool = True,
min: int | float | None = None,
Expand Down Expand Up @@ -338,6 +346,7 @@ def _number_prompt(
@no_headless
def bool_prompt(
prompt: str,
*,
default: bool = ..., # pyright: ignore[reportArgumentType] # rich uses ... to signify no default
show_default: bool = True,
warning: bool = False,
Expand All @@ -356,6 +365,7 @@ def bool_prompt(
def path_prompt(
prompt: str,
default: str | Path = ..., # pyright: ignore[reportArgumentType] # rich uses ... to signify no default
*,
show_default: bool = True,
exist_ok: bool = True,
must_exist: bool = False,
Expand Down
2 changes: 1 addition & 1 deletion zabbix_cli/output/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ class Emoji(StrEnum):
NO = EMOJI_NO

@classmethod
def fmt_bool(cls, value: bool) -> str:
def fmt_bool(cls, value: bool) -> str: # noqa: FBT001
return success(cls.YES) if value else error(cls.NO)


Expand Down
Loading

0 comments on commit dc1650c

Please sign in to comment.