mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-08 14:34:01 -06:00
Fix regex for list/dict match last item in list without comma at end.
Add some custom ordering to the json. This is so that important values like "version" don't get pushed to the end of the json.
This commit is contained in:
parent
e83ed933e2
commit
86ac4c4ab8
1 changed files with 64 additions and 9 deletions
|
@ -1,29 +1,84 @@
|
|||
import json
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
from .formatter import FileFormatter
|
||||
|
||||
|
||||
# Dictionary items with matching keys will be sorted as if they were the value
|
||||
# Example: "version" will be sorted as if it was "0"
|
||||
TOP_LEVEL_SORT_PRIORITY = {
|
||||
"version": "0",
|
||||
"name": "1",
|
||||
"inherits": "3"
|
||||
}
|
||||
|
||||
METADATA_SORT_PRIORITY = {
|
||||
"visible": "0",
|
||||
"author": "1",
|
||||
"manufacturer": "2",
|
||||
"file_formats": "3",
|
||||
"platform" : "4"
|
||||
}
|
||||
|
||||
|
||||
class DefJsonFormatter(FileFormatter):
|
||||
def format(self, file: Path):
|
||||
""" Format .def.json files according to the rules in settings """
|
||||
definition = json.loads(file.read_text())
|
||||
content = json.dumps(definition, indent=self._settings["format"].get("format-definition-indent", 4),
|
||||
sort_keys=self._settings["format"].get("format-definition-sort-keys", True))
|
||||
""" Format .def.json files according to the rules in settings.
|
||||
|
||||
You can assume that you will be running regex on standard formatted json files, because we load the json first and then
|
||||
dump it to a string. This means you only have to write regex that works on the output of json.dump()
|
||||
"""
|
||||
|
||||
definition = json.loads(file.read_text(), object_pairs_hook=OrderedDict)
|
||||
|
||||
if self._settings["format"].get("format-definition-sort-keys", True):
|
||||
definition = self.order_keys(definition)
|
||||
|
||||
content = json.dumps(definition, indent=self._settings["format"].get("format-definition-indent", 4))
|
||||
|
||||
if self._settings["format"].get("format-definition-bracket-newline", True):
|
||||
newline = re.compile(r"(\B\s+)(\"[\w\"]+)(\:\s\{)")
|
||||
content = newline.sub(r"\1\2:\1{", content)
|
||||
|
||||
if self._settings["format"].get("format-definition-single-value-single-line", True):
|
||||
single_value_dict = re.compile(r"(:)(\s*\n?.*\{\s+)(\".*)(\d*\s*\})(\s*)(,?)")
|
||||
content = single_value_dict.sub(r"\1 { \3 }\6", content)
|
||||
single_value_dict = re.compile(r"(:)(\s*\n?.*\{\s+)(\".*)(\d*\s*\})(.*\n,?)")
|
||||
content = single_value_dict.sub(r"\1 { \3 }\5", content)
|
||||
|
||||
single_value_list = re.compile(r"(:)(\s*\n?.*\[\s+)(\".*)(\d*\s*\])(\s*)(,?)")
|
||||
content = single_value_list.sub(r"\1 [ \3 ]\6", content)
|
||||
single_value_list = re.compile(r"(:)(\s*\n?.*\[\s+)(\".*)(\d*\s*\])(.*\n,?)")
|
||||
content = single_value_list.sub(r"\1 [ \3 ]\5", content)
|
||||
|
||||
if self._settings["format"].get("format-definition-paired-coordinate-array", True):
|
||||
paired_coordinates = re.compile(r"(\[)\s+(-?\d*),\s*(-?\d*)\s*(\])")
|
||||
content = paired_coordinates.sub(r"\1 \2, \3 \4", content)
|
||||
|
||||
file.write_text(content)
|
||||
file.write_text(content)
|
||||
|
||||
def order_keys(self, json_content: OrderedDict) -> OrderedDict:
|
||||
""" Orders json keys lexicographically """
|
||||
# First order all keys (Recursive) lexicographically
|
||||
json_content_text = json.dumps(json_content, sort_keys=True)
|
||||
json_content = json.loads(json_content_text, object_pairs_hook=OrderedDict)
|
||||
|
||||
# Do a custom ordered sort on the top level items in the json. This is so that keys like "version" appear at the top.
|
||||
json_content = self.custom_sort_keys(json_content, TOP_LEVEL_SORT_PRIORITY)
|
||||
|
||||
# Do a custom ordered sort on collections that are one level deep into the json
|
||||
if "metadata" in json_content.keys():
|
||||
json_content["metadata"] = self.custom_sort_keys(json_content["metadata"], METADATA_SORT_PRIORITY)
|
||||
|
||||
return json_content
|
||||
|
||||
|
||||
def custom_sort_keys(self, ordered_dictionary: OrderedDict, sort_priority: Dict[str, str]) -> OrderedDict:
|
||||
""" Orders keys in dictionary lexicographically, except for keys with matching strings in sort_priority.
|
||||
|
||||
Keys in ordered_dictionary that match keys in sort_priority will sort based on the value in sort_priority.
|
||||
|
||||
@param ordered_dictionary: A dictionary that will have it's top level keys sorted
|
||||
@param sort_priority: A mapping from string keys to alternative strings to be used instead when sorting.
|
||||
@return: A dictionary sorted by it's top level keys
|
||||
"""
|
||||
return OrderedDict(sorted(ordered_dictionary.items(), key=lambda x: sort_priority[x[0]] if str(x[0]) in sort_priority.keys() else str(x[0])))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue