mirror of
https://github.com/borgbackup/borg.git
synced 2025-02-23 14:41:43 +00:00
Merge pull request #2928 from ThomasWaldmann/json-isoformat
Json isoformat
This commit is contained in:
commit
72c8ec2583
3 changed files with 40 additions and 13 deletions
|
@ -18,7 +18,7 @@
|
|||
|
||||
from .errors import Error
|
||||
from .fs import get_keys_dir
|
||||
from .time import format_time, to_localtime, safe_timestamp, safe_s
|
||||
from .time import format_time, isoformat_time, to_localtime, safe_timestamp, safe_s
|
||||
from .usergroup import uid2user
|
||||
from .. import __version__ as borg_version
|
||||
from .. import __version_tuple__ as borg_version_tuple
|
||||
|
@ -549,6 +549,7 @@ def __init__(self, format, repository, manifest, key, *, json=False):
|
|||
if self.json:
|
||||
self.item_data = {}
|
||||
self.format_item = self.format_item_json
|
||||
self.format_time = self.format_time_json
|
||||
else:
|
||||
self.item_data = static_keys
|
||||
|
||||
|
@ -565,8 +566,8 @@ def get_item_data(self, archive_info):
|
|||
'archive': remove_surrogates(archive_info.name),
|
||||
'barchive': archive_info.name,
|
||||
'id': bin_to_hex(archive_info.id),
|
||||
'time': format_time(to_localtime(archive_info.ts)),
|
||||
'start': format_time(to_localtime(archive_info.ts)),
|
||||
'time': self.format_time(archive_info.ts),
|
||||
'start': self.format_time(archive_info.ts),
|
||||
})
|
||||
for key in self.used_call_keys:
|
||||
item_data[key] = self.call_keys[key]()
|
||||
|
@ -584,7 +585,15 @@ def get_comment(self, rs):
|
|||
return remove_surrogates(self.archive.comment) if rs else self.archive.comment
|
||||
|
||||
def get_ts_end(self):
|
||||
return format_time(to_localtime(self.archive.ts_end))
|
||||
return self.format_time(self.archive.ts_end)
|
||||
|
||||
def format_time(self, ts):
|
||||
t = to_localtime(ts)
|
||||
return format_time(t)
|
||||
|
||||
def format_time_json(self, ts):
|
||||
t = to_localtime(ts)
|
||||
return isoformat_time(t)
|
||||
|
||||
|
||||
class ItemFormatter(BaseFormatter):
|
||||
|
@ -657,6 +666,12 @@ def __init__(self, archive, format, *, json_lines=False):
|
|||
'archiveid': archive.fpr,
|
||||
}
|
||||
static_keys.update(self.FIXED_KEYS)
|
||||
if self.json_lines:
|
||||
self.item_data = {}
|
||||
self.format_item = self.format_item_json
|
||||
self.format_time = self.format_time_json
|
||||
else:
|
||||
self.item_data = static_keys
|
||||
self.format = partial_format(format, static_keys)
|
||||
self.format_keys = {f[1] for f in Formatter().parse(format)}
|
||||
self.call_keys = {
|
||||
|
@ -676,11 +691,6 @@ def __init__(self, archive, format, *, json_lines=False):
|
|||
for hash_function in hashlib.algorithms_guaranteed:
|
||||
self.add_key(hash_function, partial(self.hash_item, hash_function))
|
||||
self.used_call_keys = set(self.call_keys) & self.format_keys
|
||||
if self.json_lines:
|
||||
self.item_data = {}
|
||||
self.format_item = self.format_item_json
|
||||
else:
|
||||
self.item_data = static_keys
|
||||
|
||||
def format_item_json(self, item):
|
||||
return json.dumps(self.get_item_data(item)) + '\n'
|
||||
|
@ -758,7 +768,12 @@ def hash_item(self, hash_function, item):
|
|||
return hash.hexdigest()
|
||||
|
||||
def format_time(self, key, item):
|
||||
return format_time(safe_timestamp(item.get(key) or item.mtime))
|
||||
t = self.time(key, item)
|
||||
return format_time(t)
|
||||
|
||||
def format_time_json(self, key, item):
|
||||
t = self.time(key, item)
|
||||
return isoformat_time(t)
|
||||
|
||||
def time(self, key, item):
|
||||
return safe_timestamp(item.get(key) or item.mtime)
|
||||
|
@ -884,7 +899,7 @@ def basic_json_data(manifest, *, cache=None, extra=None):
|
|||
'mode': key.ARG_NAME,
|
||||
},
|
||||
})
|
||||
data['repository']['last_modified'] = format_time(to_localtime(manifest.last_timestamp.replace(tzinfo=timezone.utc)))
|
||||
data['repository']['last_modified'] = isoformat_time(to_localtime(manifest.last_timestamp.replace(tzinfo=timezone.utc)))
|
||||
if key.NAME.startswith('key file'):
|
||||
data['encryption']['keyfile'] = key.find_key()
|
||||
if cache:
|
||||
|
|
|
@ -87,11 +87,17 @@ def safe_timestamp(item_timestamp_ns):
|
|||
|
||||
|
||||
def format_time(t):
|
||||
"""use ISO-8601 date and time format
|
||||
"""use ISO-8601-like date and time format (human readable, with wkday and blank date/time separator)
|
||||
"""
|
||||
return t.strftime('%a, %Y-%m-%d %H:%M:%S')
|
||||
|
||||
|
||||
def isoformat_time(t):
|
||||
"""use ISO-8601 date and time format (machine readable, no wkday, no microseconds either)
|
||||
"""
|
||||
return t.strftime('%Y-%m-%dT%H:%M:%S') # note: first make all datetime objects tz aware before adding %z here.
|
||||
|
||||
|
||||
def format_timedelta(td):
|
||||
"""Format timedelta in a human friendly format
|
||||
"""
|
||||
|
|
|
@ -60,6 +60,8 @@
|
|||
|
||||
src_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
ISO_FORMAT = '%Y-%m-%dT%H:%M:%S'
|
||||
|
||||
|
||||
def exec_cmd(*args, archiver=None, fork=False, exe=None, input=b'', binary_output=False, **kw):
|
||||
if fork:
|
||||
|
@ -1304,6 +1306,7 @@ def test_info_json(self):
|
|||
repository = info_repo['repository']
|
||||
assert len(repository['id']) == 64
|
||||
assert 'last_modified' in repository
|
||||
assert datetime.strptime(repository['last_modified'], ISO_FORMAT) # must not raise
|
||||
assert info_repo['encryption']['mode'] == 'repokey'
|
||||
assert 'keyfile' not in info_repo['encryption']
|
||||
cache = info_repo['cache']
|
||||
|
@ -1846,9 +1849,11 @@ def test_list_json(self):
|
|||
list_repo = json.loads(self.cmd('list', '--json', self.repository_location))
|
||||
repository = list_repo['repository']
|
||||
assert len(repository['id']) == 64
|
||||
assert 'last_modified' in repository
|
||||
assert datetime.strptime(repository['last_modified'], ISO_FORMAT) # must not raise
|
||||
assert list_repo['encryption']['mode'] == 'repokey'
|
||||
assert 'keyfile' not in list_repo['encryption']
|
||||
archive0 = list_repo['archives'][0]
|
||||
assert datetime.strptime(archive0['time'], ISO_FORMAT) # must not raise
|
||||
|
||||
list_archive = self.cmd('list', '--json-lines', self.repository_location + '::test')
|
||||
items = [json.loads(s) for s in list_archive.splitlines()]
|
||||
|
@ -1856,6 +1861,7 @@ def test_list_json(self):
|
|||
file1 = items[1]
|
||||
assert file1['path'] == 'input/file1'
|
||||
assert file1['size'] == 81920
|
||||
assert datetime.strptime(file1['isomtime'], ISO_FORMAT) # must not raise
|
||||
|
||||
list_archive = self.cmd('list', '--json-lines', '--format={sha256}', self.repository_location + '::test')
|
||||
items = [json.loads(s) for s in list_archive.splitlines()]
|
||||
|
|
Loading…
Reference in a new issue