Skip to content

Commit a285497

Browse files
CLI: add folder properties get subcommand
1 parent 0fd005b commit a285497

2 files changed

Lines changed: 68 additions & 33 deletions

File tree

cli/common.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,38 @@ def proptagCompleter(prefix, addSuffix="", **kwargs):
6666
return c
6767

6868

69+
def printSize(value):
70+
suffix = ("B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB")
71+
index = 0
72+
prec = 0
73+
while value > 1000 and index < len(suffix)-1:
74+
value /= 1024
75+
index += 1
76+
prec = 0 if value >= 100 else 1 if value >= 10 else 2 if value >= 1 else 3
77+
return "{:.{}f} {}".format(value, prec, suffix[index])
78+
79+
80+
def printVal(cli, pv, pretty):
81+
from datetime import datetime
82+
from tools.constants import PropTags, PropTypes
83+
from tools.rop import nxTime
84+
if pv.type == PropTypes.BINARY:
85+
res = Table.Styled("[{} byte{}]".format(len(pv.val), "" if len(pv.val) == 1 else "s"), attrs=["dark"]), ""
86+
elif pv.type == PropTypes.FILETIME:
87+
timestring = datetime.fromtimestamp(nxTime(pv.val)).strftime("%Y-%m-%d %H:%M:%S")
88+
res = pv.val, cli.col(timestring, attrs=["dark"])
89+
elif pv.type in (PropTypes.STRING, PropTypes.WSTRING):
90+
res = pv.val, cli.col(printSize(len(pv.val)), attrs=["dark"])
91+
elif pv.type == PropTypes.BINARY_ARRAY:
92+
res = Table.Styled("[{} blob{}]".format(len(pv.val), "" if len(pv.val) == 1 else "s"), attrs=["dark"]), ""
93+
elif PropTypes.ismv(pv.type):
94+
res = [str(val) for val in pv.val], ""
95+
else:
96+
res = pv.val, cli.col(printSize(pv.val*PropTags.sizeFactor.get(pv.tag, 1)), attrs=["dark"])\
97+
if pv.tag in PropTags.sizeTags else ""
98+
return res if pretty else (res[0],)
99+
100+
69101
class Table:
70102
"""Helper class for pretty printing of tables."""
71103
class Styled:

cli/exmdb.py

Lines changed: 36 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# SPDX-FileCopyrightText: 2022 grommunio GmbH
44

55
from . import Cli, InvalidUseError, ArgumentParser
6-
from .common import proptagCompleter, Table
6+
from .common import printVal, proptagCompleter, Table
77

88
_perms = {
99
"readany": 0x1,
@@ -251,7 +251,7 @@ def cliExmdbFolderPermissionsShow(args):
251251
cli.require("DB")
252252
from .common import Table
253253
from services import Service
254-
from tools.rop import makeEidEx
254+
from tools.rop import makeEidEx, gcToValue
255255
fid = makeEidEx(1, args.ID)
256256
with Service("exmdb") as exmdb:
257257
ret, client = _getClient(args, exmdb)
@@ -266,39 +266,31 @@ def cliExmdbFolderPermissionsShow(args):
266266
cli.print(cli.col("Cannot show permissions for folder 0x{:x}".format(gcToValue(fid)), "yellow"))
267267

268268

269-
def cliExmdbStoreGetDelete(args):
270-
def printSize(value):
271-
suffix = ("B", "kiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB")
272-
index = 0
273-
prec = 0
274-
while value > 1000 and index < len(suffix)-1:
275-
value /= 1024
276-
index += 1
277-
prec = 0 if value >= 100 else 1 if value >= 10 else 2 if value >= 1 else 3
278-
return "{:.{}f} {}".format(value, prec, suffix[index])
279-
280-
def printVal(pv):
281-
from datetime import datetime
282-
from tools.rop import nxTime
283-
if pv.type == PropTypes.BINARY:
284-
res = Table.Styled("[{} byte{}]".format(len(pv.val), "" if len(pv.val) == 1 else "s"), attrs=["dark"]), ""
285-
elif pv.type == PropTypes.FILETIME:
286-
timestring = datetime.fromtimestamp(nxTime(pv.val)).strftime("%Y-%m-%d %H:%M:%S")
287-
res = pv.val, cli.col(timestring, attrs=["dark"])
288-
elif pv.type in (PropTypes.STRING, PropTypes.WSTRING):
289-
res = pv.val, cli.col(printSize(len(pv.val)), attrs=["dark"])
290-
elif pv.type == PropTypes.BINARY_ARRAY:
291-
res = Table.Styled("[{} blob{}]".format(len(pv.val), "" if len(pv.val) == 1 else "s"), attrs=["dark"]), ""
292-
elif PropTypes.ismv(pv.type):
293-
res = [str(val) for val in pv.val], ""
294-
else:
295-
res = pv.val, cli.col(printSize(pv.val*PropTags.sizeFactor.get(pv.tag, 1)), attrs=["dark"])\
296-
if pv.tag in PropTags.sizeTags else ""
297-
return res if pretty else (res[0],)
269+
def cliExmdbFolderPropertiesGet(args):
270+
cli = args._cli
271+
cli.require("DB")
272+
from services import Service
273+
from tools.constants import PropTags
274+
from tools.rop import makeEidEx
275+
tags = [PropTags.deriveTag(tag) for tag in args.propspec]
276+
pretty = args.format == "pretty"
277+
header = ("tag", "value", "") if pretty else ("tag", "value")
278+
fid = makeEidEx(1, args.ID)
279+
with Service("exmdb") as exmdb:
280+
ret, client = _getClient(args, exmdb)
281+
if ret:
282+
return ret
283+
if not tags:
284+
tags = client.getAllFolderProperties(fid)
285+
props = client.getFolderProperties(0, fid, tags)
286+
data = [(PropTags.lookup(prop.tag, hex(prop.tag)).lower(), *printVal(cli, prop, pretty)) for prop in props]
287+
Table(data, header, args.separator, cli.col("(No properties)", attrs=["dark"])).dump(cli, args.format)
288+
298289

290+
def cliExmdbStoreGetDelete(args):
299291
cli = args._cli
300292
cli.require("DB")
301-
from tools.constants import PropTags, PropTypes
293+
from tools.constants import PropTags
302294
from services import Service
303295
tags = [PropTags.deriveTag(tag) for tag in args.propspec]
304296
pretty = args.format == "pretty"
@@ -313,7 +305,7 @@ def printVal(pv):
313305
client.removeStoreProperties(tags)
314306
return
315307
props = client.getStoreProperties(0, tags)
316-
data = [(PropTags.lookup(prop.tag, hex(prop.tag)).lower(), *printVal(prop)) for prop in props]
308+
data = [(PropTags.lookup(prop.tag, hex(prop.tag)).lower(), *printVal(cli, prop, pretty)) for prop in props]
317309
Table(data, header, args.separator, cli.col("(No properties)", attrs=["dark"])).dump(cli, args.format)
318310

319311

@@ -407,6 +399,17 @@ def perm(x):
407399
revoke.add_argument("permission", nargs="*", type=perm, choices=PermChoices(), help="Permission name or value",
408400
metavar="permission")
409401
revoke.add_argument("-r", "--recursive", action="store_true", help="Apply to subfolders recursively")
402+
properties = foldersub.add_parser("properties")
403+
Cli.parser_stub(properties)
404+
propertiesSub = properties.add_subparsers()
405+
propertiesGet = propertiesSub.add_parser("get", help="Get properties")
406+
propertiesGet.set_defaults(_handle=cliExmdbFolderPropertiesGet)
407+
propertiesGet.add_argument("ID", type=xint, help="Folder ID")
408+
propertiesGet.add_argument("--format", choices=Table.FORMATS, help="Set output format",
409+
metavar="FORMAT", default="pretty")
410+
propertiesGet.add_argument("--separator", help="Set column separator")
411+
propertiesGet.add_argument("propspec", nargs="*", help="Properties to query")\
412+
.completer = proptagCompleter
410413

411414
store = sub.add_parser("store", help="Access store properties")
412415
Cli.parser_stub(store)

0 commit comments

Comments
 (0)