OpenShot Video Editor  2.0.0
json_data.py
Go to the documentation of this file.
1 ##
2 #
3 # @file
4 # @brief This file loads and saves settings (as JSON)
5 # @author Noah Figg <eggmunkee@hotmail.com>
6 # @author Jonathan Thomas <jonathan@openshot.org>
7 # @author Olivier Girard <eolinwen@gmail.com>
8 #
9 # @section LICENSE
10 #
11 # Copyright (c) 2008-2018 OpenShot Studios, LLC
12 # (http://www.openshotstudios.com). This file is part of
13 # OpenShot Video Editor (http://www.openshot.org), an open-source project
14 # dedicated to delivering high quality video editing and animation solutions
15 # to the world.
16 #
17 # OpenShot Video Editor is free software: you can redistribute it and/or modify
18 # it under the terms of the GNU General Public License as published by
19 # the Free Software Foundation, either version 3 of the License, or
20 # (at your option) any later version.
21 #
22 # OpenShot Video Editor is distributed in the hope that it will be useful,
23 # but WITHOUT ANY WARRANTY; without even the implied warranty of
24 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 # GNU General Public License for more details.
26 #
27 # You should have received a copy of the GNU General Public License
28 # along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
29 #
30 
31 try:
32  import json
33 except ImportError:
34  import simplejson as json
35 
36 import copy
37 
38 from classes.logger import log
39 
40 
41 ##
42 # This class which allows getting/setting of key/value settings, and loading and saving to json files.
43 # Internal storage of a dictionary. Uses json or simplejson packages to serialize and deserialize from json to dictionary.
44 # Keys are assumed to be strings, but subclasses which override get/set methods may use different key types.
45 # The write_to_file and read_from_file methods are key type agnostic.
47 
48  # Create default data storage and default data type for logging messages
49  def __init__(self):
50  self._data = {} # Private data store, accessible through the get and set methods
51  self.data_type = "json data"
52 
53  ##
54  # Get copied value of a given key in data store
55  def get(self, key):
56  key = key.lower()
57 
58  # Determine if the root element is a dictionary or list (i.e. project data or settings data)
59  if type(self._data) == list:
60  # Settings data, search for matching "setting" attribute (i.e. list)
61  # Load user setting's values (for easy merging)
62  user_values = {}
63  for item in self._data:
64  if "setting" in item and "value" in item:
65  user_values[item["setting"].lower()] = item["value"]
66 
67  # Settings data
68  return copy.deepcopy(user_values.get(key, None))
69  else:
70  # Project data (i.e dictionary)
71  return copy.deepcopy(self._data.get(key, None))
72 
73  ##
74  # Store value in key
75  def set(self, key, value):
76  key = key.lower()
77 
78  # Determine if the root element is a dictionary or list (i.e. project data or settings data)
79  if type(self._data) == list:
80  # Settings data, search for matching "setting" attribute (i.e. list)
81  # Load user setting's values (for easy merging)
82  user_values = {}
83  for item in self._data:
84  if "setting" in item and "value" in item:
85  user_values[item["setting"].lower()] = item
86 
87  # Settings data
88  user_values[key]["value"] = value
89 
90  else:
91  # Project data (i.e dictionary)
92  self._data[key] = value
93 
94  ##
95  # Merge settings files, removing invalid settings based on default settings
96  # This is only called by some sub-classes that use string keys
97  def merge_settings(self, default, user):
98 
99  # Determine if the root element is a dictionary or list (i.e. project data or settings data)
100  if type(default) == list:
101 
102  # Load user setting's values (for easy merging)
103  user_values = {}
104  for item in user:
105  if "setting" in item and "value" in item:
106  user_values[item["setting"]] = item["value"]
107 
108  # Update default values to match user values
109  for item in default:
110  user_value = user_values.get(item["setting"], None)
111  if user_value != None:
112  item["value"] = user_value
113 
114  # Return merged list
115  return default
116 
117  else:
118  # Root object is a dictionary (i.e. project data)
119  for key in default:
120  if key not in user:
121  # Add missing key to user dictionary
122  user[key] = default[key]
123 
124  # Return merged dictionary
125  return user
126 
127  ##
128  # Load JSON settings from a file
129  def read_from_file(self, file_path):
130  # log.debug("loading {}".format(file_path))
131  try:
132  with open(file_path, 'r') as f:
133  contents = f.read()
134  if contents:
135  # log.debug("loaded", contents)
136  return json.loads(contents)
137  except Exception as ex:
138  msg = ("Couldn't load {} file: {}".format(self.data_type, ex))
139  log.error(msg)
140  raise Exception(msg)
141  msg = ("Couldn't load {} file, no data.".format(self.data_type))
142  log.warning(msg)
143  raise Exception(msg)
144 
145  ##
146  # Save JSON settings to a file
147  def write_to_file(self, file_path, data):
148  # log.debug(json.dumps(data))
149  try:
150  with open(file_path, 'w') as f:
151  f.write(json.dumps(data))
152  except Exception as ex:
153  msg = ("Couldn't save {} file:\n{}\n{}".format(self.data_type, file_path, ex))
154  log.error(msg)
155  raise Exception(msg)
def write_to_file(self, file_path, data)
Save JSON settings to a file.
Definition: json_data.py:147
def get(self, key)
Get copied value of a given key in data store.
Definition: json_data.py:55
def set(self, key, value)
Store value in key.
Definition: json_data.py:75
This class which allows getting/setting of key/value settings, and loading and saving to json files...
Definition: json_data.py:46
def merge_settings(self, default, user)
Merge settings files, removing invalid settings based on default settings This is only called by some...
Definition: json_data.py:97
def read_from_file(self, file_path)
Load JSON settings from a file.
Definition: json_data.py:129