diff --git a/src/ldaptool/_main.py b/src/ldaptool/_main.py index 527ec37..94b070c 100644 --- a/src/ldaptool/_main.py +++ b/src/ldaptool/_main.py @@ -2,18 +2,74 @@ from __future__ import annotations import argparse import csv +import dataclasses import subprocess import sys import typing from ldaptool import decode, search +from ldaptool._utils import argclasses from ldaptool._utils.ldap import Result, SizeLimitExceeded +@dataclasses.dataclass(slots=True, kw_only=True) +class Arguments(search.Arguments): + raw: bool = dataclasses.field( + default=False, + metadata=argclasses.arg(help="Don't pipe output through ldap-decode"), + ) + csv: bool = dataclasses.field( + default=False, + metadata=argclasses.arg(help="CSV output - requires list of attributes"), + ) + table: bool = dataclasses.field( + default=False, + metadata=argclasses.arg( + help="Markdown table output - requires list of attributes", + ), + ) + sort: bool = dataclasses.field( + default=False, + metadata=argclasses.arg( + help="Sorted table output - defaults to markdown --table unless --csv is given", + ), + ) + + def __post_init__(self) -> None: + super(Arguments, self).__post_init__() # super() not working here, unclear why. + + # can't print both csv and markdown + if self.csv and self.table: + raise SystemExit("Can't use both --table and --csv") + + if self.sort: + if not self.table and not self.csv: + # default to markdown table + self.table = True + + if self.table: + # markdown requires underlying csv + self.csv = True + + if self.csv: + if not self.columns: + raise SystemExit("Table output requires attributes") + if self.json: + raise SystemExit("Can't use both --table / --csv / --sort and --json") + if self.human: + raise SystemExit("Can't use both --table / --csv / --sort and --human") + + if self.raw: + if self.csv: + raise SystemExit("Table output requires decode; --raw not allowed") + if self.json or self.human: + raise SystemExit("Decode options require decode; --raw not allowed") + + class _Context: def __init__(self) -> None: parser = argparse.ArgumentParser() - arguments_p = search.Arguments.add_to_parser(parser) + arguments_p = Arguments.add_to_parser(parser) args = parser.parse_args() try: self.config = search.Config.load() diff --git a/src/ldaptool/search/arguments.py b/src/ldaptool/search/arguments.py index 3445cca..1eef170 100644 --- a/src/ldaptool/search/arguments.py +++ b/src/ldaptool/search/arguments.py @@ -44,10 +44,6 @@ class Arguments(ldaptool.decode.arguments.Arguments): default=False, metadata=argclasses.arg(help="Query global catalogue (and forest root as search base)"), ) - raw: bool = dataclasses.field( - default=False, - metadata=argclasses.arg(help="Don't pipe output through ldap-decode"), - ) realm: str = dataclasses.field(metadata=argclasses.arg(required=True, help="Realm to search in")) server: typing.Optional[str] = dataclasses.field( default=None, @@ -77,22 +73,6 @@ class Arguments(ldaptool.decode.arguments.Arguments): help="Explicit search base (defaults to root of domain / forest with --gc)", ), ) - csv: bool = dataclasses.field( - default=False, - metadata=argclasses.arg(help="CSV output - requires list of attributes"), - ) - table: bool = dataclasses.field( - default=False, - metadata=argclasses.arg( - help="Markdown table output - requires list of attributes", - ), - ) - sort: bool = dataclasses.field( - default=False, - metadata=argclasses.arg( - help="Sorted table output - defaults to markdown --table unless --csv is given", - ), - ) def __post_init__(self) -> None: if not self.filter is None: @@ -107,19 +87,6 @@ class Arguments(ldaptool.decode.arguments.Arguments): # probably doesn't like empty filter? self.filter = "(objectClass=*)" - # can't print both csv and markdown - if self.csv and self.table: - raise SystemExit("Can't use both --table and --csv") - - if self.sort: - if not self.table and not self.csv: - # default to markdown table - self.table = True - - if self.table: - # markdown requires underlying csv - self.csv = True - # extract special attribute names self.columns = self.attributes # use all names for columns (headings and their order) attributes_set: dict[str, str] = {arg.lower(): arg for arg in self.attributes} # index by lowercase name @@ -135,17 +102,3 @@ class Arguments(ldaptool.decode.arguments.Arguments): if self.columns and not self.attributes: # if we only wanted fake attributes, make sure we only request 'dn' - empty list would query all attributes self.attributes = ["dn"] - - if self.csv: - if not self.columns: - raise SystemExit("Table output requires attributes") - if self.json: - raise SystemExit("Can't use both --table / --csv / --sort and --json") - if self.human: - raise SystemExit("Can't use both --table / --csv / --sort and --human") - - if self.raw: - if self.csv: - raise SystemExit("Table output requires decode; --raw not allowed") - if self.json or self.human: - raise SystemExit("Decode options require decode; --raw not allowed")