Very simple Anvil-YAML code unpacker

I don’t know if this can be useful to others, I’ll share it anyway.
I often need to keep synced various “almost-clones” apps to one another.
This simple script parses the YAML file you can download from Anvil IDE, and dumps the code under “modules”, “forms” and “server_modules” keys to approprately named “.py” files under the respective directories.
Then, it is easy to use your favourite folder-comparer to check for the differences (w.g. WinMerge).

Usage: python <script_name.py> <yaml_file_name.yaml>

Here’s the script:

import yaml
import sys
import os

def unpack_key(element, key_str):
    file_name = element[key_str]
    code = element['code']
    with open(file_name + ".py", 'wb') as f:
        f.write(code.encode("utf-8"))

def mkdir_if_not_exists(dir_name):
    try:
        os.mkdir(dir_name)
    except FileExistsError:
        print("The " + dir_name + " directory already exists!")

# read the file name from the command line if present, otherwise set it to "default"
if len(sys.argv) == 1:
    filename = "default"
else:
    filename = sys.argv[1]
# check if the ".yaml" extension is present and add it if not
if filename[-5:] != ".yaml":
    filename = filename + ".yaml"

# read the file
with open(filename, 'r') as stream:
    # parse the yaml file
    try:
        data = yaml.safe_load(stream)
    except yaml.YAMLError as exc:
        print(exc)

    # make a dir with the name of the project (filename without the ".yaml" extension)
    mkdir_if_not_exists(filename[:-5])
    os.chdir(filename[:-5])

    # make a dir with the name "client_modules" under the parent dir
    mkdir_if_not_exists("client_modules")
    os.chdir("client_modules")

    # browse all the client modules listed under the "modules" key
    for module in data["modules"]:
        # create a text file with the name of the module
        unpack_key(module, 'name')

    # make a dir with the name "server_modules" under the parent dir
    os.chdir("..")
    mkdir_if_not_exists("server_modules")
    os.chdir("server_modules")

    # browse all the server modules listed under the "modules" key
    for module in data["server_modules"]:
        # create a text file with the name of the module
        unpack_key(module, 'name')

    # make a dir with the name "client_forms" under the parent dir
    os.chdir("..")
    mkdir_if_not_exists("client_forms")
    os.chdir("client_forms")

    # browse all the client forms listed under the "forms" key
    for form in data["forms"]:
        # check if "code" key is present
        if "code" in form:
            # if it is present, read the value of the "class_name" key and of the "code" key
            unpack_key(form, 'class_name')

# print a message to the user saying that the project has been created
print("Project created successfully!")

Cheers!

2 Likes

You may want to mimic the standard Anvil folder layout:

├──client_code
├──server_code
└──theme
   └──assets

Edit 1: Which third-party YAML library are you using?

Edit 2: Here’s a tentative docstring for the top of the script:

"""Script: AnvilYamlUnpacker.py
Author: a.ercolani
Reference: https://anvil.works/forum/t/very-simple-anvil-yaml-code-unpacker/18524/2
Version: 1.0
Posted: 2023-09-05T14:13 EDT

This simple script parses the YAML file you can download from Anvil IDE, 
and dumps the code under “modules”, “forms” and “server_modules” keys 
to approprately named “.py” files under the respective directories.
Then, it is easy to use your favourite folder-comparer to check for the 
differences (w.g. WinMerge).

Requires: PyYAML (https://pypi.org/project/pyaml/).
python -m pip install pyyaml
into your intended Python Virtual Environment.

Usage: py -m AnvilYamlUnpacker <yaml_file_name.yaml>

License: ????
"""

Edit 3: per @a.ercolani 's reply.

2 Likes

I am using pyyaml

pip install pyyaml

Thanks, @a.ercolani. I’ve edited the docstring to suit.

Thank YOU @p.colbert .
Excuse me for not stopping by previously and thanking properly.

BR