mirror of
https://github.com/beetbox/beets.git
synced 2025-12-29 20:12:33 +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
d9582f4bea
4 changed files with 34 additions and 7 deletions
|
|
@ -54,6 +54,14 @@ class ExportPlugin(BeetsPlugin):
|
|||
'sort_keys': True
|
||||
}
|
||||
},
|
||||
'jsonlines': {
|
||||
# JSON Lines formatting options.
|
||||
'formatting': {
|
||||
'ensure_ascii': False,
|
||||
'separators': (',', ': '),
|
||||
'sort_keys': True
|
||||
}
|
||||
},
|
||||
'csv': {
|
||||
# CSV module formatting options.
|
||||
'formatting': {
|
||||
|
|
@ -95,7 +103,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), jsonlines, csv, or xml"
|
||||
)
|
||||
return [cmd]
|
||||
|
||||
|
|
@ -103,6 +111,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 +139,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):
|
||||
|
|
@ -147,7 +161,7 @@ class ExportFormat(object):
|
|||
|
||||
@classmethod
|
||||
def factory(cls, file_type, **kwargs):
|
||||
if file_type == "json":
|
||||
if file_type in ["json", "jsonlines"]:
|
||||
return JsonFormat(**kwargs)
|
||||
elif file_type == "csv":
|
||||
return CSVFormat(**kwargs)
|
||||
|
|
@ -167,6 +181,7 @@ class JsonFormat(ExportFormat):
|
|||
|
||||
def export(self, data, **kwargs):
|
||||
json.dump(data, self.out_stream, cls=ExportEncoder, **kwargs)
|
||||
self.out_stream.write('\n')
|
||||
|
||||
|
||||
class CSVFormat(ExportFormat):
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ New features:
|
|||
`discogs_artistid`
|
||||
:bug: `3413`
|
||||
* :doc:`/plugins/export`: Added new ``-f`` (``--format``) flag;
|
||||
which allows for the ability to export in json, csv and xml.
|
||||
which allows for the ability to export in json, jsonlines, csv and xml.
|
||||
Thanks to :user:`austinmm`.
|
||||
:bug:`3402`
|
||||
* :doc:`/plugins/unimported`: lets you find untracked files in your library directory.
|
||||
|
|
|
|||
|
|
@ -39,14 +39,15 @@ The ``export`` command has these command-line options:
|
|||
|
||||
* ``--append``: Appends the data to the file instead of writing.
|
||||
|
||||
* ``--format`` or ``-f``: Specifies the format the data will be exported as. If not informed, JSON will be used by default. The format options include csv, json and xml.
|
||||
* ``--format`` or ``-f``: Specifies the format the data will be exported as. If not informed, JSON will be used by default. The format options include csv, json, `jsonlines <https://jsonlines.org/>`_ and xml.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
To configure the plugin, make a ``export:`` section in your configuration
|
||||
file.
|
||||
For JSON export, these options are available under the ``json`` key:
|
||||
For JSON export, these options are available under the ``json`` and
|
||||
``jsonlines`` keys:
|
||||
|
||||
- **ensure_ascii**: Escape non-ASCII characters with ``\uXXXX`` entities.
|
||||
- **indent**: The number of spaces for indentation.
|
||||
|
|
|
|||
|
|
@ -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