1

I am trying to parse all plugin tags from an XML file and build a dict using a Plugin class I created. I really do not understand the error and the context of the error.

.append() does not seem to work when I try to initialize the plugin_dict as a list. Also when I try to call __init__() function like plugin = Plugin(), I get an error that Plugin needs at least 1 argument when I have already implemented a __init__(self) function which requires no arguments.

Here is the code from main.py

from plugin import Plugin
from bs4 import BeautifulSoup

def parse():
    file = open('../data/windows.xml')
    soup = BeautifulSoup(file, 'xml')
    plugins = soup.find_all('plugin')
    plugin_dict = []
    for plugin in plugins:
        plugin_dict.append(Plugin(plugin))
    return plugin_dict

where plugin.py is:

class Plugin(object):
    __name = 'Unknown'
    __vendor = {}
    __vendor_name = 'Unknown, Inc.'
    __vendor_producturl = 'http://www.example.com/product'
    __vendor = [__vendor_name, __vendor_producturl]
    __version = {}
    __version_code = '0.0.0.0'
    __version_release_date = '01-01-1970'
    __version = [__version_code, __version_release_date]
    __properties = {}
    __beta = False
    __vst3 = False
    __x64 = False
    __category = 'synth/effect'
    __properties = {__beta, __vst3, __x64, __category}
    __magnet_uri = {}
    __iss_links = {}
    __download_uri = {}
    __downloads = {}
    __downloads = [__magnet_uri, __iss_links, __download_uri]

    def __init__(self):
        '''Create an empty instance for later use'''
        self.name = str(__name)
        self.version = {}
        self.version.code = str(__version[0])
        self.version.releasedate = str(__version[1])
        self.version = [self.version.code, self.version.releasedate]
        self.vendor = {}
        self.vendor.name = str(__vendor_name)
        self.vendor.producturl = str(__vendor_producturl)
        self.vendor = [self.vendor.name, self.vendor.producturl]
        self.properties = {}
        self.properties.beta = bool(__properties[0])
        self.properties.vst3 = bool(__properties[1])
        self.properties.x64 = bool(__properties[2])
        self.properties.category = str(__properties[3])
        self.properties = [self.properties.beta, self.properties.vst3, self.properties.x64, self.properties.category]
        self.magneturi = list(__magnet_uri)
        self.isslinks = list(__iss_links)
        self.downloaduri = list(__download_uri)
        self.downloads = {}
        self.downloads = [self.magneturi, self.isslinks, self.downloaduri]
        self.product_dict = {}
        self.product_dict = [self.name, self.vendor, self.properties, self.downloads]
        return self.product_dict

    def __init__(self, plugin):
        self.name = plugin['name']
        self.version = {}
        self.version.code = plugin.version.code.string
        self.version.releasedate = plugin.version.releasedate.string
        self.version = [self.version.code, self.version.releasedate]
        self.vendor= {}
        self.vendor.name = plugin.vendor.string
        self.vendor.producturl = plugin.vendor['url']
        self.vendor = [self.vendor.name, self.vendor.producturl]
        self.properties = {}
        self.properties.beta = plugin['beta']
        self.properties.vst3 = plugin['vst3']
        self.properties.x64 = plugin['x64']
        self.properties.category = plugin['category']
        self.properties = [self.properties.beta, self.properties.vst3, self.properties.x64, self.properties.category]
        magnet_uri_dict = {}
        magnet_uri_dict = plugin.find_all('magnet')
        for magnet_uri in magnet_uri_dict:
            self.magneturi.append[magnet_uri.name, magnet_uri.string]
        iss_link_dict = {}
        iss_link_dict = plugin.find_all('iss/*')
        for iss_link in iss_link_dict:
            self.isslinks.append(iss_link.string)
        download_uri_dict = {}
        download_uri_dict = plugin.find_all('download-uri/*')
        for download_uri in download_uri_dict:
            self.downloaduri.append(download_uri.string)
        self.downloads = {}
        self.downloads = [self.magneturi, self.isslinks, self.downloaduri]
        self.product_dict = {}
        self.product_dict = [self.name, self.vendor, self.properties, self.downloads]
        return self.product_dict

and a plugin tag in windows.xml looks like:

    <plugin name="Serum" vst3="false" beta="false" x64="true" category="synth">
        <vendor url="">Xfer Records</vendor>
        <version>
            <code>1.248</code>
            <release-date>13-03-2019</release-date>
        </version>
        <download-uri>
            <zippy>PLACEHOLDER</zippy>
            <openload>PLACEHOLDER</openload>
            <sr-files>PLACEHOLDER</sr-files>
        </download-uri>
        <iss>
            <mirror1>PLACEHOLDER</mirror1>
            <mirror2>PLACEHOLDER</mirror2>
            <mirror3>PLACEHOLDER</mirror3>
        </iss>
        <magnet type="default"></magnet>
    </plugin>

I think I am going wrong with defining self.version.something; I never saw an example like that. I just used it for better classification of the XML into an object


If you think that I should mark this as python-3.x also then please tell

demberto
  • 489
  • 5
  • 15

1 Answers1

1

You are trying to set an attribute on a dictionary

self.version = {}
self.version.code = plugin.version.code.string  # This won't work

If you would like to set a key on the dictionary you need to use the following syntax

self.version['code'] = plugin.version.code.string

You have redefined the __init__ method of your class, python does not support this. In your code you have replaced the first definition with the second. Plugin() would fail with a message saying there was a missing required parameter "plugin"

Iain Shelvington
  • 31,030
  • 3
  • 31
  • 50
  • thanks for your answer. how can i use both the __init__() methods? – demberto Aug 03 '19 at 20:45
  • The "pythonic" way to have multiple initialisers/constructors is to have a base `__init__` method that handles the default case and then to have a `classmethod` that either passes additional parameters to the base method or sets the attributes after calling the base method. This answer shows the basics https://stackoverflow.com/a/682545/548562 – Iain Shelvington Aug 03 '19 at 20:49