Initial Commit: working json -> hierarchical yaml unpacking
This commit is contained in:
commit
6a486c4f36
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.egg-info/
|
||||||
|
__pycache__/
|
42
poetry.lock
generated
Normal file
42
poetry.lock
generated
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
[[package]]
|
||||||
|
name = "pathvalidate"
|
||||||
|
version = "2.3.0"
|
||||||
|
description = "pathvalidate is a Python library to sanitize/validate a string such as filenames/file-paths/etc."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
test = ["allpairspy", "click", "faker", "pytest"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyyaml"
|
||||||
|
version = "5.3.1"
|
||||||
|
description = "YAML parser and emitter for Python"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
lock-version = "1.0"
|
||||||
|
python-versions = "^3.8"
|
||||||
|
content-hash = "9174acecc4f28cb786e63beb6c608fe788fb186e6485c64749543309a2b53121"
|
||||||
|
|
||||||
|
[metadata.files]
|
||||||
|
pathvalidate = [
|
||||||
|
{file = "pathvalidate-2.3.0-py3-none-any.whl", hash = "sha256:1697c8ea71ff4c48e7aa0eda72fe4581404be8f41e51a17363ef682dd6824d35"},
|
||||||
|
{file = "pathvalidate-2.3.0.tar.gz", hash = "sha256:32d30dbacb711c16bb188b12ce7e9a46b41785f50a12f64500f747480a4b6ee3"},
|
||||||
|
]
|
||||||
|
pyyaml = [
|
||||||
|
{file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"},
|
||||||
|
{file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"},
|
||||||
|
{file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"},
|
||||||
|
{file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"},
|
||||||
|
{file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"},
|
||||||
|
{file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"},
|
||||||
|
{file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"},
|
||||||
|
{file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"},
|
||||||
|
{file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"},
|
||||||
|
{file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"},
|
||||||
|
{file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
|
||||||
|
]
|
19
pyproject.toml
Normal file
19
pyproject.toml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[tool.poetry]
|
||||||
|
name = "tts_yaml_unpacker"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = ""
|
||||||
|
authors = ["Adam Goldsmith <adam@adamgoldsmith.name>"]
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = "^3.8"
|
||||||
|
pathvalidate = "^2.3.0"
|
||||||
|
pyyaml = "^5.3.1"
|
||||||
|
|
||||||
|
[tool.poetry.dev-dependencies]
|
||||||
|
|
||||||
|
[tool.poetry.scripts]
|
||||||
|
tts_yaml_unpacker = 'tts_yaml_unpacker:main'
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry>=0.12"]
|
||||||
|
build-backend = "poetry.masonry.api"
|
107
tts_yaml_unpacker.py
Executable file
107
tts_yaml_unpacker.py
Executable file
@ -0,0 +1,107 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import json
|
||||||
|
import yaml
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathvalidate import sanitize_filename
|
||||||
|
|
||||||
|
|
||||||
|
class IncludeTag:
|
||||||
|
yaml_tag = '!include'
|
||||||
|
|
||||||
|
def __init__(self, target):
|
||||||
|
self.target = target
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def to_yaml(cls, dumper, node):
|
||||||
|
return dumper.represent_scalar(cls.yaml_tag, node.target)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_yaml(cls, loader, node):
|
||||||
|
base_dir = os.path.dirname(loader.stream.name)
|
||||||
|
target = os.path.join(base_dir, node.value)
|
||||||
|
with open(target) as f:
|
||||||
|
if target.endswith('.yaml'):
|
||||||
|
return yaml.load(f, Loader=yaml.Loader)
|
||||||
|
else:
|
||||||
|
return f.read()
|
||||||
|
|
||||||
|
|
||||||
|
yaml.add_constructor('!include', IncludeTag.from_yaml)
|
||||||
|
yaml.add_representer(IncludeTag, IncludeTag.to_yaml)
|
||||||
|
|
||||||
|
|
||||||
|
def uniqueName(obj):
|
||||||
|
if 'SaveName' in obj:
|
||||||
|
return obj['SaveName']
|
||||||
|
return f"{obj['Name']} {obj['Nickname']} {obj['GUID']}"
|
||||||
|
|
||||||
|
|
||||||
|
def shouldRecurse(obj, subobject_prop):
|
||||||
|
return subobject_prop in obj \
|
||||||
|
and obj.get('Name') not in ('Deck', 'DeckCustom') \
|
||||||
|
and len(obj[subobject_prop]) > 1
|
||||||
|
|
||||||
|
|
||||||
|
def recursivelyUnpackObject(parent_dir, obj,
|
||||||
|
subobject_prop='ContainedObjects', base_name=None):
|
||||||
|
def convertObjectsToIncludes(objects):
|
||||||
|
for subObj in objects:
|
||||||
|
filename = recursivelyUnpackObject(file_base_path, subObj)
|
||||||
|
yield IncludeTag(os.path.join(obj_base_name, filename))
|
||||||
|
|
||||||
|
obj_base_name = base_name or sanitize_filename(uniqueName(obj))
|
||||||
|
file_base_path = os.path.join(parent_dir, obj_base_name)
|
||||||
|
|
||||||
|
if shouldRecurse(obj, subobject_prop):
|
||||||
|
os.makedirs(file_base_path, exist_ok=True)
|
||||||
|
|
||||||
|
obj[subobject_prop] = list(
|
||||||
|
convertObjectsToIncludes(obj[subobject_prop]))
|
||||||
|
|
||||||
|
if 'LuaScript' in obj and len(obj['LuaScript']) > 0:
|
||||||
|
with open(file_base_path + '.ttslua', 'w') as f:
|
||||||
|
f.write(obj['LuaScript'])
|
||||||
|
|
||||||
|
obj['LuaScript'] = IncludeTag(obj_base_name + '.ttslua')
|
||||||
|
|
||||||
|
with open(file_base_path + '.yaml', 'w') as f:
|
||||||
|
yaml.dump(obj, f)
|
||||||
|
|
||||||
|
return obj_base_name + '.yaml'
|
||||||
|
|
||||||
|
|
||||||
|
def unpackJson(json_file, output_name):
|
||||||
|
with open(json_file) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
recursivelyUnpackObject(
|
||||||
|
'', data, subobject_prop='ObjectStates', base_name=output_name)
|
||||||
|
|
||||||
|
|
||||||
|
def packYaml(yaml_file, output_json_file):
|
||||||
|
with open(yaml_file) as f:
|
||||||
|
data = yaml.load(f, Loader=yaml.Loader)
|
||||||
|
|
||||||
|
with open(output_json_file, 'w') as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
def usage():
|
||||||
|
print(f"Usage: {sys.argv[0]} <unpack|pack> <input> <output>")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 4:
|
||||||
|
usage()
|
||||||
|
elif sys.argv[1] == 'unpack':
|
||||||
|
unpackJson(sys.argv[2], sys.argv[3])
|
||||||
|
elif sys.argv[1] == 'pack':
|
||||||
|
packYaml(sys.argv[2], sys.argv[3])
|
||||||
|
else:
|
||||||
|
usage()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user