source: orange/Orange/OrangeCanvas/help/provider.py @ 11263:9f8fc6d26e58

Revision 11263:9f8fc6d26e58, 3.6 KB checked in by Ales Erjavec <ales.erjavec@…>, 15 months ago (diff)

Added canvas help search system.

Line 
1"""
2
3"""
4import os
5import logging
6
7from StringIO import StringIO
8from urlparse import urljoin
9
10from PyQt4.QtCore import QObject, QUrl
11
12from PyQt4.QtNetwork import (
13    QNetworkAccessManager, QNetworkDiskCache, QNetworkRequest, QNetworkReply
14)
15
16
17from .intersphinx import read_inventory_v1, read_inventory_v2
18
19from .. import config
20
21log = logging.getLogger(__name__)
22
23
24class HelpProvider(QObject):
25    def __init__(self, parent=None):
26        QObject.__init__(self, parent)
27
28    def search(self, description):
29        raise NotImplementedError
30
31
32class IntersphinxHelpProvider(HelpProvider):
33    def __init__(self, parent=None, target=None, inventory=None):
34        HelpProvider.__init__(self, parent)
35        self.target = target
36
37        if inventory is None:
38            if is_url_local(self.target):
39                inventory = os.path.join(self.target, "objects.inv")
40            else:
41                inventory = urljoin(self.target, "objects.inv")
42
43        self.inventory = inventory
44
45        self.islocal = bool(QUrl(inventory).toLocalFile())
46
47        self._fetch_inventory()
48
49    def search(self, description):
50        if description.help_ref:
51            ref = description.help_ref
52        else:
53            ref = description.name
54
55        if not hasattr(self, "items"):
56            self._reply.waitForReadyRead(2000)
57
58        labels = self.items.get("std:label", {})
59        entry = labels.get(ref.lower(), None)
60        if entry is not None:
61            _, _, url, _ = entry
62            return url
63        else:
64            raise KeyError(ref)
65
66    def _fetch_inventory(self):
67        cache_dir = config.cache_dir()
68        cache_dir = os.path.join(cache_dir, "help", "intersphinx")
69
70        try:
71            os.makedirs(cache_dir)
72        except OSError:
73            pass
74
75        url = QUrl(self.inventory)
76
77        if not self.islocal:
78            # fetch and cache the inventory file
79            manager = QNetworkAccessManager(self)
80            cache = QNetworkDiskCache()
81            cache.setCacheDirectory(cache_dir)
82            manager.setCache(cache)
83            req = QNetworkRequest(url)
84
85            self._reply = manager.get(req)
86            manager.finished.connect(self._on_finished)
87        else:
88            self._load_inventory(open(unicode(url.toLocalFile()), "rb"))
89
90    def _on_finished(self, reply):
91        del self._reply
92        if reply.error() != QNetworkReply.NoError:
93            log.error("An error occurred while fetching "
94                      "intersphinx inventory {0!r}".format(self.inventory))
95
96            self._error = reply.error(), reply.errorString()
97
98        else:
99            contents = reply.readAll()
100            self._load_inventory(StringIO(contents))
101
102    def _load_inventory(self, stream):
103        version = stream.readline().rstrip()
104        if self.islocal:
105            join = os.path.join
106        else:
107            join = urljoin
108
109        if version == "# Sphinx inventory version 1":
110            inventory = read_inventory_v1(stream, self.target, join)
111        elif version == "# Sphinx inventory version 2":
112            inventory = read_inventory_v2(stream, self.target, join)
113        else:
114            log.error("Invalid/unknown intersphinx inventory format.")
115            self._error = (ValueError,
116                           "{0} does not seem to be an intersphinx "
117                           "inventory file".format(self.target))
118
119        self.items = inventory
120
121
122def qurl_query_items(url):
123    items = []
124    for key, value in url.queryItems():
125        items.append((unicode(key), unicode(value)))
126    return items
127
128
129def is_url_local(url):
130    return bool(QUrl(url).toLocalFile())
Note: See TracBrowser for help on using the repository browser.