Compare commits
4 Commits
ca0aa23c27
...
7979fa7cc7
Author | SHA1 | Date | |
---|---|---|---|
7979fa7cc7 | |||
ba6cc242f1 | |||
a936734cee | |||
dd225c8b7a |
@ -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 detailed or simplified attribute values)
|
* JSON stream (with simplified or detailed 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
7
debian/changelog
vendored
@ -1,3 +1,10 @@
|
|||||||
|
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 ]
|
||||||
|
@ -55,13 +55,17 @@ 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(help="Use full json output"),
|
metadata=argclasses.arg(
|
||||||
)
|
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:
|
||||||
@ -85,15 +89,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.json:
|
if self.full_json:
|
||||||
raise SystemExit("Can't use both table output and --json")
|
raise SystemExit("Can't use both table output and --json")
|
||||||
if self.human:
|
if self.json:
|
||||||
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.json or self.human:
|
if self.full_json or self.json:
|
||||||
raise SystemExit("Decode options require decode; --raw not allowed")
|
raise SystemExit("Decode options require decode; --raw not allowed")
|
||||||
|
|
||||||
|
|
||||||
@ -183,7 +187,7 @@ class _Context:
|
|||||||
num_responses = 0
|
num_responses = 0
|
||||||
num_entries = 0
|
num_entries = 0
|
||||||
|
|
||||||
ldif_output = not (self.arguments.json or self.arguments.human)
|
ldif_output = not (self.arguments.full_json or self.arguments.json)
|
||||||
|
|
||||||
if ldif_output:
|
if ldif_output:
|
||||||
print("# extended LDIF")
|
print("# extended LDIF")
|
||||||
@ -214,11 +218,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.human:
|
elif self.arguments.json:
|
||||||
decoder.read_and_emit_human(dn=dn, entry=entry, file=stream)
|
decoder.read_and_emit_simple_json(dn=dn, entry=entry, file=stream)
|
||||||
else:
|
else:
|
||||||
assert self.arguments.json
|
assert self.arguments.full_json
|
||||||
decoder.read_and_emit_json(dn=dn, entry=entry, file=stream)
|
decoder.read_and_emit_full_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}")
|
||||||
|
|
||||||
|
@ -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] = self.arguments.human_separator.join(attr.human() for attr in attrs)
|
emit[name] = [attr.human() for attr in attrs]
|
||||||
return emit
|
return emit
|
||||||
|
|
||||||
def emit_human(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None:
|
def emit_simple_json(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_human(self, *, dn: str, entry: TEntry, file: typing.IO[str] = sys.stdout) -> None:
|
def read_and_emit_simple_json(self, *, dn: str, entry: TEntry, file: typing.IO[str] = sys.stdout) -> None:
|
||||||
self.emit_human(dn=dn, obj=self.read(dn=dn, entry=entry), file=file)
|
self.emit_simple_json(dn=dn, obj=self.read(dn=dn, entry=entry), file=file)
|
||||||
|
|
||||||
def json(self, *, dn: str, obj: TDecoded) -> dict[str, str]:
|
def full_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_json(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None:
|
def emit_full_json(self, *, dn: str, obj: TDecoded, file: typing.IO[str] = sys.stdout) -> None:
|
||||||
emit = self.json(dn=dn, obj=obj)
|
emit = self.full_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_json(self, *, dn: str, entry: TEntry, file: typing.IO[str] = sys.stdout) -> None:
|
def read_and_emit_full_json(self, *, dn: str, entry: TEntry, file: typing.IO[str] = sys.stdout) -> None:
|
||||||
self.emit_json(dn=dn, obj=self.read(dn=dn, entry=entry), file=file)
|
self.emit_full_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)
|
||||||
|
Loading…
Reference in New Issue
Block a user