Port install/remove functions to new PK 0.8.x API
[appstream:software-center.git] / apt-xapian-index-plugin / software-center.py
1 # add software-center custom metadata to the index
2
3 import apt
4 import os
5 import sys
6 import xapian
7
8 sys.path.insert(0, "/usr/share/software-center")
9 from softwarecenter.enums import (
10     CustomKeys,
11     XapianValues,
12     )
13 from softwarecenter.db.update import index_name
14 from softwarecenter.distro import get_distro
15
16
17 class SoftwareCenterMetadataPlugin:
18
19     def info(self):
20         """
21         Return general information about the plugin.
22
23         The information returned is a dict with various keywords:
24
25          timestamp (required)
26            the last modified timestamp of this data source.  This will be used
27            to see if we need to update the database or not.  A timestamp of 0
28            means that this data source is either missing or always up to date.
29          values (optional)
30            an array of dicts { name: name, desc: description }, one for every
31            numeric value indexed by this data source.
32
33         Note that this method can be called before init.  The idea is that, if
34         the timestamp shows that this plugin is currently not needed, then the
35         long initialisation can just be skipped.
36         """
37         file = apt.apt_pkg.config.find_file("Dir::Cache::pkgcache")
38         if not os.path.exists(file):
39             return dict(timestamp=0)
40         return dict(timestamp=os.path.getmtime(file))
41
42     def init(self, info, progress):
43         """
44         If needed, perform long initialisation tasks here.
45
46         info is a dictionary with useful information.  Currently it contains
47         the following values:
48
49           "values": a dict mapping index mnemonics to index numbers
50
51         The progress indicator can be used to report progress.
52         """
53         self.indexer = xapian.TermGenerator()
54
55     def doc(self):
56         """
57         Return documentation information for this data source.
58
59         The documentation information is a dictionary with these keys:
60           name: the name for this data source
61           shortDesc: a short description
62           fullDoc: the full description as a chapter in ReST format
63         """
64         return dict(
65             name="SoftwareCenterMetadata",
66             shortDesc="SoftwareCenter meta information",
67             fullDoc="""
68             Software-center metadata
69             It uses the prefixes:
70               AA for the Application name
71               AP for the Package name
72               AC for the categories
73               AT to "application" for applications
74             It sets the following xapian values from the software-center
75             enums:
76               XapianValues.ICON
77               XapianValues.ICON_NEEDS_DOWNLOAD
78               XapianValues.ICON_URL
79               XapianValues.SCREENSHOT_URLS
80               XapianValues.THUMBNAIL_URL
81             """)
82
83     def index(self, document, pkg):
84         """
85         Update the document with the information from this data source.
86
87         document  is the document to update
88         pkg       is the python-apt Package object for this package
89         """
90         ver = pkg.candidate
91         # if there is no version or the AppName custom key is not
92         # found we can skip the pkg
93         if ver is None or not CustomKeys.APPNAME in ver.record:
94             return
95         # we want to index the following custom fields:
96         #   XB-AppName,
97         #   XB-Icon,
98         #   XB-Screenshot-Url,
99         #   XB-Thumbnail-Url,
100         #   XB-Category
101         if CustomKeys.APPNAME in ver.record:
102             name = ver.record[CustomKeys.APPNAME]
103             self.indexer.set_document(document)
104             index_name(document, name, self.indexer)
105             # we pretend to be an application
106             document.add_term("AT" + "application")
107             # and we inject a custom component value to indicate "independent"
108             document.add_value(XapianValues.ARCHIVE_SECTION, "independent")
109         if CustomKeys.ICON in ver.record:
110             icon = ver.record[CustomKeys.ICON]
111             document.add_value(XapianValues.ICON, icon)
112             # calculate the url and add it (but only if there actually is
113             # a url)
114             try:
115                 distro = get_distro()
116                 if distro:
117                     base_uri = ver.uri
118                     # new python-apt returns None instead of StopIteration
119                     if base_uri:
120                         url = distro.get_downloadable_icon_url(base_uri, icon)
121                         document.add_value(XapianValues.ICON_URL, url)
122             except StopIteration:
123                 pass
124         if CustomKeys.SCREENSHOT_URLS in ver.record:
125             screenshot_url = ver.record[CustomKeys.SCREENSHOT_URLS]
126             document.add_value(XapianValues.SCREENSHOT_URLS, screenshot_url)
127         if CustomKeys.THUMBNAIL_URL in ver.record:
128             url = ver.record[CustomKeys.THUMBNAIL_URL]
129             document.add_value(XapianValues.THUMBNAIL_URL, url)
130         if CustomKeys.CATEGORY in ver.record:
131             categories_str = ver.record[CustomKeys.CATEGORY]
132             for cat in categories_str.split(";"):
133                 if cat:
134                     document.add_term("AC" + cat.lower())
135
136     def indexDeb822(self, document, pkg):
137         """
138         Update the document with the information from this data source.
139
140         This is alternative to index, and it is used when indexing with package
141         data taken from a custom Packages file.
142
143         document  is the document to update
144         pkg       is the Deb822 object for this package
145         """
146         # NOTHING here, does not make sense for non-downloadable data
147         return
148
149
150 def init():
151     """
152     Create and return the plugin object.
153     """
154     return SoftwareCenterMetadataPlugin()