mirror of
https://github.com/beetbox/beets.git
synced 2025-12-15 21:14:19 +01:00
export: Add --format=jsonlines option
This adds support for the JSON Lines format as documented at https://jsonlines.org/. In this mode the data is output incrementally, whereas the other modes load every item into memory and don't produce output until the end.
This commit is contained in:
parent
78f976320d
commit
591038d246
2 changed files with 39 additions and 10 deletions
|
|
@ -43,16 +43,22 @@ class ExportPlugin(BeetsPlugin):
|
|||
def __init__(self):
|
||||
super(ExportPlugin, self).__init__()
|
||||
|
||||
json_formatting_options = {
|
||||
'ensure_ascii': False,
|
||||
'indent': 4,
|
||||
'separators': (',', ': '),
|
||||
'sort_keys': True
|
||||
}
|
||||
|
||||
self.config.add({
|
||||
'default_format': 'json',
|
||||
'json': {
|
||||
# JSON module formatting options.
|
||||
'formatting': {
|
||||
'ensure_ascii': False,
|
||||
'indent': 4,
|
||||
'separators': (',', ': '),
|
||||
'sort_keys': True
|
||||
}
|
||||
'formatting': json_formatting_options,
|
||||
},
|
||||
'jsonlines': {
|
||||
# JSON Lines formatting options.
|
||||
'formatting': json_formatting_options,
|
||||
},
|
||||
'csv': {
|
||||
# CSV module formatting options.
|
||||
|
|
@ -95,7 +101,7 @@ class ExportPlugin(BeetsPlugin):
|
|||
)
|
||||
cmd.parser.add_option(
|
||||
u'-f', u'--format', default='json',
|
||||
help=u"the output format: json (default), csv, or xml"
|
||||
help=u"the output format: json (default), json-lines, csv, or xml"
|
||||
)
|
||||
return [cmd]
|
||||
|
||||
|
|
@ -103,6 +109,7 @@ class ExportPlugin(BeetsPlugin):
|
|||
file_path = opts.output
|
||||
file_mode = 'a' if opts.append else 'w'
|
||||
file_format = opts.format or self.config['default_format'].get(str)
|
||||
file_format_is_line_based = (file_format == 'jsonlines')
|
||||
format_options = self.config[file_format]['formatting'].get(dict)
|
||||
|
||||
export_format = ExportFormat.factory(
|
||||
|
|
@ -130,9 +137,14 @@ class ExportPlugin(BeetsPlugin):
|
|||
continue
|
||||
|
||||
data = key_filter(data)
|
||||
items += [data]
|
||||
|
||||
export_format.export(items, **format_options)
|
||||
if file_format_is_line_based:
|
||||
export_format.export(data, **format_options)
|
||||
else:
|
||||
items += [data]
|
||||
|
||||
if not file_format_is_line_based:
|
||||
export_format.export(items, **format_options)
|
||||
|
||||
|
||||
class ExportFormat(object):
|
||||
|
|
@ -149,6 +161,8 @@ class ExportFormat(object):
|
|||
def factory(cls, file_type, **kwargs):
|
||||
if file_type == "json":
|
||||
return JsonFormat(**kwargs)
|
||||
if file_type == "jsonlines":
|
||||
return JsonFormat(newline_at_end=True, **kwargs)
|
||||
elif file_type == "csv":
|
||||
return CSVFormat(**kwargs)
|
||||
elif file_type == "xml":
|
||||
|
|
@ -162,11 +176,15 @@ class ExportFormat(object):
|
|||
|
||||
class JsonFormat(ExportFormat):
|
||||
"""Saves in a json file"""
|
||||
def __init__(self, file_path, file_mode=u'w', encoding=u'utf-8'):
|
||||
def __init__(self, file_path, file_mode=u'w', encoding=u'utf-8',
|
||||
newline_at_end=False):
|
||||
super(JsonFormat, self).__init__(file_path, file_mode, encoding)
|
||||
self.newline_at_end = newline_at_end
|
||||
|
||||
def export(self, data, **kwargs):
|
||||
json.dump(data, self.out_stream, cls=ExportEncoder, **kwargs)
|
||||
if self.newline_at_end:
|
||||
self.out_stream.write('\n')
|
||||
|
||||
|
||||
class CSVFormat(ExportFormat):
|
||||
|
|
|
|||
|
|
@ -66,6 +66,17 @@ class ExportPluginTest(unittest.TestCase, TestHelper):
|
|||
self.assertTrue(key in json_data)
|
||||
self.assertEqual(val, json_data[key])
|
||||
|
||||
def test_jsonlines_output(self):
|
||||
item1 = self.create_item()
|
||||
out = self.execute_command(
|
||||
format_type='jsonlines',
|
||||
artist=item1.artist
|
||||
)
|
||||
json_data = json.loads(out)
|
||||
for key, val in self.test_values.items():
|
||||
self.assertTrue(key in json_data)
|
||||
self.assertEqual(val, json_data[key])
|
||||
|
||||
def test_csv_output(self):
|
||||
item1 = self.create_item()
|
||||
out = self.execute_command(
|
||||
|
|
|
|||
Loading…
Reference in a new issue