Skip to content

Instantly share code, notes, and snippets.

@evandrocoan
Created January 10, 2023 00:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save evandrocoan/7804f10e442e5a379bf1c604b96dc123 to your computer and use it in GitHub Desktop.
Save evandrocoan/7804f10e442e5a379bf1c604b96dc123 to your computer and use it in GitHub Desktop.
Convert Anki decks from JSON to YAML and vice versa.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import timeit
import datetime
import argparse
import tempfile
import pathlib
# python3 -m pip install pyyaml
# import yaml
# https://stackoverflow.com/questions/71836675/force-pyyaml-to-write-multiline-string-literals-regardless-of-string-content
# python3 -m pip install ruamel.yaml
import ruamel.yaml as yaml
import sys
import json
from pathlib import Path
from typing import Optional
g_start_time = timeit.default_timer()
SCRIPT_DIRECTORY = pathlib.Path(__file__).parent.resolve()
def main() -> Optional[int]:
argumentsNamespace = g_argumentParser.parse_args()
if argumentsNamespace.help:
g_argumentParser.print_help()
return
to_json = argumentsNamespace.to_json
fast_scandir(SCRIPT_DIRECTORY, max_recursion=1, to_json=to_json)
def fast_scandir(current_directory: Path, max_recursion=1, to_json=False, recursion_depth=0):
subfolders = []
for subpath in os.scandir(current_directory):
fullpath = current_directory / subpath
if fullpath.is_dir():
if recursion_depth < max_recursion:
subfolders.extend(
fast_scandir(
fullpath,
max_recursion=max_recursion,
to_json=to_json,
recursion_depth=recursion_depth + 1
)
)
else:
if to_json:
if fullpath.name == "deck.yml":
newjsonpath = fullpath.with_suffix(".json")
with open(fullpath, 'r') as readyml, \
tempfile.NamedTemporaryFile(
mode="w",
dir=current_directory,
suffix=".ignore",
newline='\r\n',
encoding='utf8',
) as temporaryfile:
print(f"Converting to json {fullpath}.", file=sys.stderr)
json.dump(yaml.safe_load(readyml), temporaryfile, indent=4, ensure_ascii=False)
temporaryfile.flush() # atomic write for safety
os.replace(temporaryfile.name, newjsonpath)
print_time()
# NamedTemporaryFile with delete=True should not fail if file already deleted
# https://bugs.python.org/issue29573
with open(temporaryfile.name, 'w') as fake:
fake.write("nothing")
else:
if fullpath.name == "deck.json":
newymlpath = fullpath.with_suffix(".yml")
with open(fullpath, 'r') as readjson, \
tempfile.NamedTemporaryFile(
mode="w",
dir=current_directory,
suffix=".ignore",
newline='\n',
encoding='utf8',
) as temporaryfile:
print(f"Converting to yml {fullpath}.", file=sys.stderr)
yaml.dump(json.load(readjson), temporaryfile,
default_flow_style=False,
default_style='|',
allow_unicode=True)
temporaryfile.flush() # atomic write for safety
os.replace(temporaryfile.name, newymlpath)
print_time()
# NamedTemporaryFile with delete=True should not fail if file already deleted
# https://bugs.python.org/issue29573
with open(temporaryfile.name, 'w') as fake:
fake.write("nothing")
return subfolders
# Call it without the start parameter to print the time since the last call
def print_time(start=None):
global g_start_time
start = g_start_time if start is None else start
end = timeit.default_timer()
print("Time elapsed %s... " % datetime.timedelta(seconds=end-start),
end="\n", file=sys.stderr)
g_start_time = end
# Simple python program example to run tests together with your code using pytest
# https://gist.github.com/evandrocoan/69aeaee3e16ad77fc5c889cfd55fc698
g_argumentParser = argparse.ArgumentParser(
description = \
"""
Convert Anki decks from JSON to YAML and vice versa.
""",
formatter_class=argparse.RawTextHelpFormatter,
add_help=False,
)
g_argumentParser.add_argument( "-h", "--help", action="store_true",
help= """
Show this help message and exits.
""" )
g_argumentParser.add_argument( "-j", "--to-json", action="store_true", default=None,
help=
"""
Convert Anki deck back from YAML to json.
""" )
if __name__ == '__main__':
start = timeit.default_timer()
code = main()
print_time(start)
sys.exit(code if code else 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment