Search code examples
pythonplistlib

Insert Python dictionary into another dictionary, to generate .plist file?


I'm trying to generate a .plist file with plistlib library, available in macOS Python 2.7.

The following code works:

#!/usr/bin/env python

from plistlib import writePlist

patches = [
    {
        'Arch': 'x86_64',
        'Base': 'early'
    },
    {
        'Arch': 'x86_64',
        'Base': 'late'
    }
]

result = [
    {
        'Arch': 'x86_64',
        'BundlePath': 'Alpha.kext'
    },
    {
        'Arch': 'x86_64',
        'BundlePath': 'Beta.kext'
    }
]
for i in patches:
    result.append(dict(i))

settings = {
    'Kernel': {
        'Add': result
    }
}
writePlist(settings, 'config.plist')

And produces a config.plist file with the content:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Kernel</key>
    <dict>
        <key>Add</key>
        <array>
            <dict>
                <key>Arch</key>
                <string>x86_64</string>
                <key>BundlePath</key>
                <string>Alpha.kext</string>
            </dict>
            <dict>
                <key>Arch</key>
                <string>x86_64</string>
                <key>BundlePath</key>
                <string>Beta.kext</string>
            </dict>
            <dict>
                <key>Arch</key>
                <string>x86_64</string>
                <key>Base</key>
                <string>early</string>
            </dict>
            <dict>
                <key>Arch</key>
                <string>x86_64</string>
                <key>Base</key>
                <string>late</string>
            </dict>
        </array>
    </dict>
</dict>
</plist>

However, my config.plist requires to have the patches dictionaries inside another dictionary:

            <dict>
                <dict>
                    <key>Arch</key>
                    <string>x86_64</string>
                    <key>Base</key>
                    <string>early</string>

The correct config file must look like (see lines 21 and 22 in an editor):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Kernel</key>
    <dict>
        <key>Add</key>
        <array>
            <dict>
                <key>Arch</key>
                <string>x86_64</string>
                <key>BundlePath</key>
                <string>Alpha.kext</string>
            </dict>
            <dict>
                <key>Arch</key>
                <string>x86_64</string>
                <key>BundlePath</key>
                <string>Beta.kext</string>
            </dict>
            <dict>
                <dict>
                    <key>Arch</key>
                    <string>x86_64</string>
                    <key>Base</key>
                    <string>early</string>
                </dict>
                <dict>
                    <key>Arch</key>
                    <string>x86_64</string>
                    <key>Base</key>
                    <string>late</string>
                </dict>
            </dict>
        </array>
    </dict>
</dict>
</plist>

How can I edit my setup.py file to produce the proper dictionary inside dictionary output? In case you wander why I split the code, is because this is a very simplified format, the actual code quite more complex. Therefore, I need a solution within the above code design. Thank you for your help.


Solution

  • The desired output does not look correct. Your "dictionary of dictionary" does not have a key with it. I suspect it should be something like

    <dict>
        <key>Patches</key>
        <array>
            <dict>
                <key>Arch</key>
                ...
            </dict>
            <dict>
                <key>Arch</key>
                ...
            </dict>
        </array>
    </dict>
    

    If so, here is how you could do that, using the key of "Patches".

    patches = [
        {
            'Arch': 'x86_64',
            'Base': 'early'
        },
        {
            'Arch': 'x86_64',
            'Base': 'late'
        }
    ]
    
    result = [
        {
            'Arch': 'x86_64',
            'BundlePath': 'Alpha.kext'
        },
        {
            'Arch': 'x86_64',
            'BundlePath': 'Beta.kext'
        }
    ]
    result.append({"Patches": patches})
    
    settings = {
        'Kernel': {
            'Add': result
        }
    }
    writePlist(settings, 'config.plist')
    

    Output

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
            <key>Kernel</key>
            <dict>
                    <key>Add</key>
                    <array>
                            <dict>
                                    <key>Arch</key>
                                    <string>x86_64</string>
                                    <key>BundlePath</key>
                                    <string>Alpha.kext</string>
                            </dict>
                            <dict>
                                    <key>Arch</key>
                                    <string>x86_64</string>
                                    <key>BundlePath</key>
                                    <string>Beta.kext</string>
                            </dict>
                            <dict>
                                    <key>Patches</key>
                                    <array>
                                            <dict>
                                                    <key>Arch</key>
                                                    <string>x86_64</string>
                                                    <key>Base</key>
                                                    <string>early</string>
                                            </dict>
                                            <dict>
                                                    <key>Arch</key>
                                                    <string>x86_64</string>
                                                    <key>Base</key>
                                                    <string>late</string>
                                            </dict>
                                    </array>
                            </dict>
                    </array>
            </dict>
    </dict>
    </plist>