source: orange/Orange/misc/widgetparser.py @ 9699:e24510156e0d

Revision 9699:e24510156e0d, 3.4 KB checked in by anze <anze.staric@…>, 2 years ago (diff)

Moved widgetparser and fileutil to Orange.misc

Line 
1import xml.dom.minidom
2import re, os
3from fileutil import xml_text_of
4from fileutil import create_text_element
5from fileutil import _zip_open
6
7re_inputs = re.compile(r'[ \t]+self.inputs\s*=\s*(?P<signals>\[[^]]*\])', re.DOTALL)
8re_outputs = re.compile(r'[ \t]+self.outputs\s*=\s*(?P<signals>\[[^]]*\])', re.DOTALL)
9re_tuple = re.compile(r"\(([^)]+)\)")
10
11def _getSignalList(regex, data):
12    inmo = regex.search(data)
13    if inmo:
14        return str([tuple([y[0] in "'\"" and y[1:-1] or str(y) for y in (x.strip() for x in ttext.group(1).split(","))])
15                    for ttext in re_tuple.finditer(inmo.group("signals"))])
16    else:
17        return "[]"
18
19class WidgetMetaData:
20    xmlAttrs = ["name", "description", "contact", "category", "icon", "hasDoc"]
21
22    def __init__(self, data, defaultCategory="Prototypes", enforceDefaultCategory=False, filename=None, hasDoc="0"):  # data can either be a string with module (.py file) contents or an xml.dom.Element
23        if not filename and data.__class__ is xml.dom.minidom.Element:  # XML (as returned by toXml())
24            self.name=""
25            self.icon=""
26            self.priority=""
27            self.description=""
28            self.category=""
29            self.tags=""
30            self.filename=None
31            self.hasDoc = hasDoc
32            for attr in self.xmlAttrs:
33                nodes = data.getElementsByTagName(attr)
34                if nodes:
35                    setattr(self, attr, xml_text_of(nodes[0]))
36            if data.hasAttribute("filename"):
37                self.filename = data.getAttribute("filename")
38        else:   # python module
39            setattr(self, "filename", filename)
40            for attr, deflt in (("name", None), ("contact", "") , ("icon", "icons/Unknown.png"), ("priority", "5000"), ("description", ""), ("category", defaultCategory), ("tags", "")):
41                istart, iend = data.find("<"+attr+">"), data.find("</"+attr+">")
42                setattr(self, attr, istart >= 0 and iend >= 0 and data[istart+2+len(attr):iend].strip() or deflt)
43            if enforceDefaultCategory:
44                self.category = defaultCategory
45            if not self.name:
46                raise Exception("Not an Orange widget module.")
47            self.hasDoc = hasDoc
48            self.inputList = _getSignalList(re_inputs, data)
49            self.outputList = _getSignalList(re_outputs, data)
50
51    def clone(self):
52        return WidgetMetaData(self.toXml())
53
54    def toXml(self):
55        widgetTag = xml.dom.minidom.Element("widget")
56        for attr in self.xmlAttrs:
57            if hasattr(self, attr):
58                widgetTag.appendChild(create_text_element(attr, getattr(self, attr)))
59        if "filename" in self.__dict__ and self.filename:
60            widgetTag.setAttribute("filename", self.filename)
61        return widgetTag
62
63_widgetModuleName = re.compile(r"widgets/(prototypes/|)[^/]*\.py$")
64def widgetsXml(oaoZip):
65    files = oaoZip.namelist()
66    widgetsTag = xml.dom.minidom.Element("widgets")
67    for file in files:
68        if re.match(_widgetModuleName, file):
69            try:
70                filename = file[8:]
71                meta = WidgetMetaData(_zip_open(oaoZip, file).read(), "None", filename=filename, hasDoc="1" if ("doc/widgets/%s.htm" % (os.path.splitext(filename)[0][2:]) in files) else "0")
72            except:
73                continue   # Probably not an Orange widget module
74            widgetsTag.appendChild(meta.toXml())
75    return widgetsTag
Note: See TracBrowser for help on using the repository browser.