mirror of
https://github.com/fergalmoran/picard.git
synced 2026-02-24 08:33:59 +00:00
Switch back to using JSON for import / export scripts
This commit is contained in:
@@ -44,8 +44,6 @@ from enum import (
|
||||
import json
|
||||
import uuid
|
||||
|
||||
import yaml
|
||||
|
||||
from picard.config import get_config
|
||||
from picard.const import (
|
||||
DEFAULT_FILE_NAMING_FORMAT,
|
||||
@@ -128,7 +126,7 @@ class PicardScriptType(IntEnum):
|
||||
FILENAMING = 2
|
||||
|
||||
|
||||
class ScriptYamlImportError(Exception):
|
||||
class ScriptImportError(Exception):
|
||||
def __init__(self, *args):
|
||||
super().__init__(*args)
|
||||
|
||||
@@ -244,15 +242,17 @@ class PicardScript():
|
||||
new_object._set_new_id()
|
||||
return new_object
|
||||
|
||||
def to_yaml(self):
|
||||
"""Converts the properties of the script object to a YAML formatted string. Note that only property
|
||||
names listed in `OUTPUT_FIELDS` will be included in the output.
|
||||
# TODO: Enable once PyYAML requirement resolved with Python 3.8
|
||||
#
|
||||
# def to_yaml(self):
|
||||
# """Converts the properties of the script object to a YAML formatted string. Note that only property
|
||||
# names listed in `OUTPUT_FIELDS` will be included in the output.
|
||||
|
||||
Returns:
|
||||
str: The properties of the script object formatted as a YAML string.
|
||||
"""
|
||||
items = {key: getattr(self, key) for key in dir(self) if key in self.OUTPUT_FIELDS}
|
||||
return yaml.dump(items)
|
||||
# Returns:
|
||||
# str: The properties of the script object formatted as a YAML string.
|
||||
# """
|
||||
# items = {key: getattr(self, key) for key in dir(self) if key in self.OUTPUT_FIELDS}
|
||||
# return yaml.dump(items)
|
||||
|
||||
def to_json(self, indent=None):
|
||||
"""Converts the properties of the script object to a JSON formatted string. Note that only property
|
||||
@@ -267,25 +267,27 @@ class PicardScript():
|
||||
items = {key: getattr(self, key) for key in dir(self) if key in self.OUTPUT_FIELDS}
|
||||
return json.dumps(items, indent=indent, sort_keys=True)
|
||||
|
||||
@classmethod
|
||||
def create_from_yaml(cls, yaml_string):
|
||||
"""Creates an instance based on the contents of the YAML string provided.
|
||||
Properties in the YAML string that are not found in the script object are ignored.
|
||||
# TODO: Enable once PyYAML requirement resolved with Python 3.8
|
||||
#
|
||||
# @classmethod
|
||||
# def create_from_yaml(cls, yaml_string):
|
||||
# """Creates an instance based on the contents of the YAML string provided.
|
||||
# Properties in the YAML string that are not found in the script object are ignored.
|
||||
|
||||
Args:
|
||||
yaml_string (str): YAML string containing the property settings.
|
||||
# Args:
|
||||
# yaml_string (str): YAML string containing the property settings.
|
||||
|
||||
Returns:
|
||||
object: An instance of the class, populated from the property settings in the YAML string.
|
||||
"""
|
||||
new_object = cls()
|
||||
yaml_dict = yaml.safe_load(yaml_string)
|
||||
if not isinstance(yaml_dict, dict):
|
||||
raise ScriptYamlImportError(N_("File content not a dictionary"))
|
||||
if 'title' not in yaml_dict or 'script' not in yaml_dict:
|
||||
raise ScriptYamlImportError(N_('Invalid script package'))
|
||||
new_object._update_from_dict(yaml_dict)
|
||||
return new_object
|
||||
# Returns:
|
||||
# object: An instance of the class, populated from the property settings in the YAML string.
|
||||
# """
|
||||
# new_object = cls()
|
||||
# yaml_dict = yaml.safe_load(yaml_string)
|
||||
# if not isinstance(yaml_dict, dict):
|
||||
# raise ScriptImportError(N_("File content not a dictionary"))
|
||||
# if 'title' not in yaml_dict or 'script' not in yaml_dict:
|
||||
# raise ScriptImportError(N_('Invalid script package'))
|
||||
# new_object._update_from_dict(yaml_dict)
|
||||
# return new_object
|
||||
|
||||
@classmethod
|
||||
def create_from_json(cls, json_string):
|
||||
@@ -299,7 +301,10 @@ class PicardScript():
|
||||
object: An instance of the class, populated from the property settings in the JSON string.
|
||||
"""
|
||||
new_object = cls()
|
||||
new_object.title = ''
|
||||
new_object.update_from_json(json_string)
|
||||
if not (new_object['title'] and new_object['script']):
|
||||
raise ScriptImportError(N_('Invalid script package'))
|
||||
return new_object
|
||||
|
||||
def update_from_json(self, json_string):
|
||||
@@ -309,7 +314,11 @@ class PicardScript():
|
||||
Args:
|
||||
json_string (str): JSON string containing the property settings.
|
||||
"""
|
||||
self._update_from_dict(json.loads(json_string))
|
||||
try:
|
||||
decoded_string = json.loads(json_string)
|
||||
except json.decoder.JSONDecodeError:
|
||||
raise ScriptImportError(N_("Unable to decode JSON string"))
|
||||
self._update_from_dict(decoded_string)
|
||||
|
||||
|
||||
class FileNamingScript(PicardScript):
|
||||
|
||||
@@ -41,8 +41,8 @@ from picard.file import File
|
||||
from picard.script import (
|
||||
FileNamingScript,
|
||||
ScriptError,
|
||||
ScriptImportError,
|
||||
ScriptParser,
|
||||
ScriptYamlImportError,
|
||||
get_file_naming_script_presets,
|
||||
)
|
||||
from picard.util.settingsoverride import SettingsOverride
|
||||
@@ -58,11 +58,7 @@ from picard.ui.ui_scripteditor_details import Ui_ScriptDetails
|
||||
from picard.ui.widgets.scriptdocumentation import ScriptingDocumentationWidget
|
||||
|
||||
|
||||
class ScriptImportError(OptionsCheckError):
|
||||
pass
|
||||
|
||||
|
||||
class ScriptExportError(OptionsCheckError):
|
||||
class ScriptFileError(OptionsCheckError):
|
||||
pass
|
||||
|
||||
|
||||
@@ -271,7 +267,7 @@ class ScriptEditorPage(PicardDialog):
|
||||
|
||||
self.FILE_TYPE_ALL = _("All Files") + " (*)"
|
||||
self.FILE_TYPE_SCRIPT = _("Picard Script Files") + " (*.pts *.txt)"
|
||||
self.FILE_TYPE_PACKAGE = _("Picard Naming Script Package") + " (*.pnsp *.yaml)"
|
||||
self.FILE_TYPE_PACKAGE = _("Picard Naming Script Package") + " (*.pnsp *.json)"
|
||||
|
||||
self.SCRIPT_TITLE_SYSTEM = _("System: %s")
|
||||
self.SCRIPT_TITLE_USER = _("User: %s")
|
||||
@@ -619,7 +615,7 @@ class ScriptEditorPage(PicardDialog):
|
||||
"""
|
||||
log.error(fmt, filename, msg)
|
||||
error_message = _(fmt) % (filename, _(msg))
|
||||
self.display_error(ScriptImportError(_(title), error_message))
|
||||
self.display_error(ScriptFileError(_(title), error_message))
|
||||
|
||||
def output_file_error(self, fmt, filename, msg):
|
||||
"""Log file error and display error message dialog.
|
||||
@@ -656,8 +652,8 @@ class ScriptEditorPage(PicardDialog):
|
||||
return
|
||||
if file_type == self.FILE_TYPE_PACKAGE:
|
||||
try:
|
||||
script_item = FileNamingScript().create_from_yaml(file_content)
|
||||
except ScriptYamlImportError as error:
|
||||
script_item = FileNamingScript().create_from_json(file_content)
|
||||
except ScriptImportError as error:
|
||||
self.output_file_error(FILE_ERROR_DECODE, filename, error)
|
||||
return
|
||||
else:
|
||||
@@ -690,7 +686,7 @@ class ScriptEditorPage(PicardDialog):
|
||||
filename = name
|
||||
log.debug('Exporting naming script file: %s' % filename)
|
||||
if file_type == self.FILE_TYPE_PACKAGE:
|
||||
script_text = script_item.to_yaml()
|
||||
script_text = script_item.to_json(indent=4)
|
||||
try:
|
||||
with open(filename, 'w', encoding='utf8') as o_file:
|
||||
o_file.write(script_text)
|
||||
|
||||
@@ -6,4 +6,3 @@ mutagen==1.45.1
|
||||
pyobjc-core==6.2.2
|
||||
pyobjc-framework-Cocoa==6.2.2
|
||||
PyQt5==5.13.1
|
||||
PyYAML==5.4.1
|
||||
|
||||
@@ -6,4 +6,3 @@ mutagen==1.45.1
|
||||
pyobjc-core==6.2.2
|
||||
pyobjc-framework-Cocoa==6.2.2
|
||||
PyQt5==5.15.4
|
||||
PyYAML==5.4.1
|
||||
|
||||
@@ -5,4 +5,3 @@ markdown==3.3.4
|
||||
mutagen==1.45.1
|
||||
PyQt5==5.15.4
|
||||
pywin32==300
|
||||
PyYAML==5.4.1
|
||||
|
||||
@@ -7,4 +7,3 @@ pyobjc-core<7.0; sys_platform == 'darwin'
|
||||
pyobjc-framework-Cocoa<7.0; sys_platform == 'darwin'
|
||||
PyQt5>=5.10
|
||||
pywin32; sys_platform == 'win32'
|
||||
PyYAML==5.4.1
|
||||
|
||||
@@ -27,6 +27,7 @@ from test.picardtestcase import PicardTestCase
|
||||
from picard.script import (
|
||||
FileNamingScript,
|
||||
PicardScript,
|
||||
ScriptImportError,
|
||||
)
|
||||
|
||||
|
||||
@@ -125,10 +126,10 @@ class ScriptClassesTest(PicardTestCase):
|
||||
|
||||
def test_script_object_9(self):
|
||||
# Test that an exception is raised when creating or updating using an invalid JSON string
|
||||
with self.assertRaises(JSONDecodeError):
|
||||
with self.assertRaises(ScriptImportError):
|
||||
test_script = PicardScript().create_from_json('Not a JSON string')
|
||||
test_script = PicardScript(title='Script 1', script='Script text', id='12345', last_updated='2021-04-26', script_language_version='1.0')
|
||||
with self.assertRaises(JSONDecodeError):
|
||||
with self.assertRaises(ScriptImportError):
|
||||
test_script.update_from_json('Not a JSON string')
|
||||
|
||||
def test_naming_script_object_1(self):
|
||||
|
||||
Reference in New Issue
Block a user