Compare commits

..

No commits in common. "7979fa7cc728dced37c0374a74ef078fbd2606eb" and "ca0aa23c276fe199376c90faa8010ead7db531fb" have entirely different histories.

4 changed files with 24 additions and 35 deletions

View File

@ -9,7 +9,7 @@ CLI tool to query LDAP/AD servers
* Integration with password managers * Integration with password managers
* Various output formats * Various output formats
* Classic LDIF * Classic LDIF
* JSON stream (with simplified or detailed attribute values) * JSON stream (with detailed or simplified attribute values)
* CSV * CSV
* Markdown table with stretched columns (for viewing in CLI/for monospaces fonts); requires csvlook from [csvkit](https://csvkit.readthedocs.io/) * Markdown table with stretched columns (for viewing in CLI/for monospaces fonts); requires csvlook from [csvkit](https://csvkit.readthedocs.io/)
* HTML * HTML

7
debian/changelog vendored
View File

@ -1,10 +1,3 @@
ldaptool (0.6-1) unstable; urgency=medium
* move --json to --full_json; remove --human JSON output, replace with --json, but don't merge multiple values - use list instead
* run ./fmt.sh to fix lint
-- Stefan Bühler <stefan.buehler@tik.uni-stuttgart.de> Thu, 11 May 2023 17:30:04 +0200
ldaptool (0.5-1) unstable; urgency=medium ldaptool (0.5-1) unstable; urgency=medium
[ Daniel Dizdarevic ] [ Daniel Dizdarevic ]

View File

@ -55,17 +55,13 @@ class Arguments(search.Arguments):
help="Sorted table output - defaults to markdown --table unless --csv is given", help="Sorted table output - defaults to markdown --table unless --csv is given",
), ),
) )
full_json: bool = dataclasses.field(
default=False,
metadata=argclasses.arg(
help="Use full json output (dn as str, attributes as list of dicts containing various represenatations)",
),
)
json: bool = dataclasses.field( json: bool = dataclasses.field(
default=False, default=False,
metadata=argclasses.arg( metadata=argclasses.arg(help="Use full json output"),
help="Use simple json output (dn as str, attributes map to list of human-readable strings)", )
), human: bool = dataclasses.field(
default=False,
metadata=argclasses.arg(help="Use simple json output (join multiple values of one attribute)"),
) )
def __post_init__(self) -> None: def __post_init__(self) -> None:
@ -89,15 +85,15 @@ class Arguments(search.Arguments):
if self.table_output: if self.table_output:
if not self.columns: if not self.columns:
raise SystemExit("Table output requires attributes") raise SystemExit("Table output requires attributes")
if self.full_json:
raise SystemExit("Can't use both table output and --json")
if self.json: if self.json:
raise SystemExit("Can't use both table output and --json")
if self.human:
raise SystemExit("Can't use both table output and --human") raise SystemExit("Can't use both table output and --human")
if self.raw: if self.raw:
if self.table_output: if self.table_output:
raise SystemExit("Table output requires decode; --raw not allowed") raise SystemExit("Table output requires decode; --raw not allowed")
if self.full_json or self.json: if self.json or self.human:
raise SystemExit("Decode options require decode; --raw not allowed") raise SystemExit("Decode options require decode; --raw not allowed")
@ -187,7 +183,7 @@ class _Context:
num_responses = 0 num_responses = 0
num_entries = 0 num_entries = 0
ldif_output = not (self.arguments.full_json or self.arguments.json) ldif_output = not (self.arguments.json or self.arguments.human)
if ldif_output: if ldif_output:
print("# extended LDIF") print("# extended LDIF")
@ -218,11 +214,11 @@ class _Context:
num_entries += 1 num_entries += 1
if ldif_output: if ldif_output:
decoder.read_and_emit_ldif(dn=dn, entry=entry, file=stream) decoder.read_and_emit_ldif(dn=dn, entry=entry, file=stream)
elif self.arguments.json: elif self.arguments.human:
decoder.read_and_emit_simple_json(dn=dn, entry=entry, file=stream) decoder.read_and_emit_human(dn=dn, entry=entry, file=stream)
else: else:
assert self.arguments.full_json assert self.arguments.json
decoder.read_and_emit_full_json(dn=dn, entry=entry, file=stream) decoder.read_and_emit_json(dn=dn, entry=entry, file=stream)
except SizeLimitExceeded as e: except SizeLimitExceeded as e:
raise SystemExit(f"Error: {e}") raise SystemExit(f"Error: {e}")

View File

@ -192,30 +192,30 @@ class Decoder:
def human(self, *, dn: str, obj: TDecoded) -> dict[str, str]: def human(self, *, dn: str, obj: TDecoded) -> dict[str, str]:
emit: dict[str, typing.Any] = dict(dn=dn) emit: dict[str, typing.Any] = dict(dn=dn)
for name, attrs in obj.items(): for name, attrs in obj.items():
emit[name] = [attr.human() for attr in attrs] emit[name] = self.arguments.human_separator.join(attr.human() for attr in attrs)
return emit return emit
def emit_simple_json(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None: def emit_human(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None:
emit = self.human(dn=dn, obj=obj) emit = self.human(dn=dn, obj=obj)
json.dump(emit, file, ensure_ascii=False) json.dump(emit, file, ensure_ascii=False)
print(file=file) # terminate output dicts by newline print(file=file) # terminate output dicts by newline
def read_and_emit_simple_json(self, *, dn: str, entry: TEntry, file: typing.IO[str] = sys.stdout) -> None: def read_and_emit_human(self, *, dn: str, entry: TEntry, file: typing.IO[str] = sys.stdout) -> None:
self.emit_simple_json(dn=dn, obj=self.read(dn=dn, entry=entry), file=file) self.emit_human(dn=dn, obj=self.read(dn=dn, entry=entry), file=file)
def full_json(self, *, dn: str, obj: TDecoded) -> dict[str, str]: def json(self, *, dn: str, obj: TDecoded) -> dict[str, str]:
emit: dict[str, typing.Any] = dict(dn=dn) emit: dict[str, typing.Any] = dict(dn=dn)
for name, attrs in obj.items(): for name, attrs in obj.items():
emit[name] = [attr.to_json() for attr in attrs] emit[name] = [attr.to_json() for attr in attrs]
return emit return emit
def emit_full_json(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None: def emit_json(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None:
emit = self.full_json(dn=dn, obj=obj) emit = self.json(dn=dn, obj=obj)
json.dump(emit, file, ensure_ascii=False) json.dump(emit, file, ensure_ascii=False)
print(file=file) # terminate output dicts by newline print(file=file) # terminate output dicts by newline
def read_and_emit_full_json(self, *, dn: str, entry: TEntry, file: typing.IO[str] = sys.stdout) -> None: def read_and_emit_json(self, *, dn: str, entry: TEntry, file: typing.IO[str] = sys.stdout) -> None:
self.emit_full_json(dn=dn, obj=self.read(dn=dn, entry=entry), file=file) self.emit_json(dn=dn, obj=self.read(dn=dn, entry=entry), file=file)
def emit_ldif(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None: def emit_ldif(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None:
print(f"dn: {dn}", file=file) print(f"dn: {dn}", file=file)