Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.py

changeset 6011
e6af0dcfbb35
child 6047
39586a2de99d
equal deleted inserted replaced
6010:7ef7d47a0ad5 6011:e6af0dcfbb35
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2015 - 2017 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to show details about a package.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 basestring # __IGNORE_WARNING__
13 except NameError:
14 basestring = str
15
16 from PyQt5.QtCore import Qt, QLocale
17 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QTreeWidgetItem, \
18 QLabel, QHeaderView
19
20 from .Ui_PipPackageDetailsDialog import Ui_PipPackageDetailsDialog
21
22
23 class PipPackageDetailsDialog(QDialog, Ui_PipPackageDetailsDialog):
24 """
25 Class documentation goes here.
26 """
27 def __init__(self, detailsData, downloadsData, parent=None):
28 """
29 Constructor
30
31 @param detailsData package details (dict)
32 @param downloadsData downloads information (dict)
33 @param parent reference to the parent widget (QWidget)
34 """
35 super(PipPackageDetailsDialog, self).__init__(parent)
36 self.setupUi(self)
37
38 self.__locale = QLocale()
39 self.__packageTypeMap = {
40 "sdist": self.tr("Source"),
41 "bdist_wheel": self.tr("Python Wheel"),
42 "bdist_egg": self.tr("Python Egg"),
43 "bdist_wininst": self.tr("MS Windows Installer"),
44 "bdist_msi": self.tr("MS Windows Installer"),
45 "bdist_rpm": self.tr("Unix Installer"),
46 "bdist_deb": self.tr("Unix Installer"),
47 "bdist_dumb": self.tr("Archive"),
48 }
49
50 self.__populateDetails(detailsData)
51 self.__populateDownloadUrls(downloadsData)
52 self.__populateRequiresProvides(detailsData)
53
54 def __populateDetails(self, detailsData):
55 """
56 Private method to populate the details tab.
57
58 @param detailsData package details (dict)
59 """
60 self.packageNameLabel.setText(
61 "<h1>{0} {1}</h1".format(self.__sanitize(detailsData["name"]),
62 self.__sanitize(detailsData["version"])))
63 self.summaryLabel.setText(
64 self.__sanitize(detailsData["summary"][:240]))
65 self.descriptionEdit.setPlainText(
66 self.__sanitize(detailsData["description"]))
67 self.authorLabel.setText(self.__sanitize(detailsData["author"]))
68 self.authorEmailLabel.setText(
69 '<a href="mailto:{0}">{0}</a>'.format(
70 self.__sanitize(detailsData["author_email"])))
71 self.licenseLabel.setText(self.__sanitize(detailsData["license"]))
72 self.platformLabel.setText(self.__sanitize(detailsData["platform"]))
73 self.homePageLabel.setText(
74 '<a href="{0}">{0}</a>'.format(
75 self.__sanitize(detailsData["home_page"], forUrl=True)))
76 self.packageUrlLabel.setText(
77 '<a href="{0}">{0}</a>'.format(
78 self.__sanitize(detailsData["package_url"], forUrl=True)))
79 self.releaseUrlLabel.setText(
80 '<a href="{0}">{0}</a>'.format(
81 self.__sanitize(detailsData["release_url"], forUrl=True)))
82 self.docsUrlLabel.setText(
83 '<a href="{0}">{0}</a>'.format(
84 self.__sanitize(detailsData["docs_url"], forUrl=True)))
85 self.downloadsDayLabel.setText(self.__locale.toString(
86 detailsData["downloads"]["last_day"]))
87 self.downloadsWeekLabel.setText(self.__locale.toString(
88 detailsData["downloads"]["last_week"]))
89 self.downloadsMonthLabel.setText(self.__locale.toString(
90 detailsData["downloads"]["last_month"]))
91 self.classifiersList.addItems(detailsData["classifiers"])
92
93 self.buttonBox.button(QDialogButtonBox.Close).setDefault(True)
94 self.buttonBox.button(QDialogButtonBox.Close).setFocus(
95 Qt.OtherFocusReason)
96
97 def __populateDownloadUrls(self, downloadsData):
98 """
99 Private method to populate the download URLs tab.
100
101 @param downloadsData downloads information (dict)
102 """
103 index = self.infoWidget.indexOf(self.urls)
104 if downloadsData:
105 self.infoWidget.setTabEnabled(index, True)
106 for download in downloadsData:
107 itm = QTreeWidgetItem(self.downloadUrlsList, [
108 "",
109 self.__packageTypeMap[download["packagetype"]]
110 if download["packagetype"] in self.__packageTypeMap
111 else "",
112 download["python_version"]
113 if download["python_version"] != "source"
114 else "",
115 self.__locale.toString(download["downloads"]),
116 self.__formatUploadDate(download["upload_time"]),
117 self.__formatSize(download["size"]),
118 ])
119 if download["has_sig"]:
120 pgpLink = ' (<a href="{0}">pgp</a>)'.format(
121 download["url"] + ".asc")
122 else:
123 pgpLink = ""
124 urlLabel = QLabel('<a href="{0}#md5={2}">{1}</a>{3}'.format(
125 download["url"], download["filename"],
126 download["md5_digest"], pgpLink))
127 urlLabel.setTextInteractionFlags(Qt.LinksAccessibleByMouse)
128 urlLabel.setOpenExternalLinks(True)
129 self.downloadUrlsList.setItemWidget(itm, 0, urlLabel)
130 header = self.downloadUrlsList.header()
131 header.resizeSections(QHeaderView.ResizeToContents)
132 else:
133 self.infoWidget.setTabEnabled(index, False)
134
135 def __populateRequiresProvides(self, detailsData):
136 """
137 Private method to populate the requires/provides tab.
138
139 @param detailsData package details (dict)
140 """
141 populated = False
142
143 if "requires" in detailsData:
144 self.requiredPackagesList.addItems(detailsData["requires"])
145 populated = True
146 if "requires_dist" in detailsData:
147 self.requiredDistributionsList.addItems(
148 detailsData["requires_dist"])
149 populated = True
150 if "provides" in detailsData:
151 self.providedPackagesList.addItems(detailsData["provides"])
152 populated = True
153 if "provides_dist" in detailsData:
154 self.providedDistributionsList.addItems(
155 detailsData["provides_dist"])
156 populated = True
157
158 index = self.infoWidget.indexOf(self.requires)
159 self.infoWidget.setTabEnabled(index, populated)
160
161 def __sanitize(self, text, forUrl=False):
162 """
163 Private method to clean-up the given text.
164
165 @param text raw text (string)
166 @param forUrl flag indicating to sanitize an URL text (boolean)
167 @return processed text (string)
168 """
169 if text == "UNKNOWN":
170 text = ""
171 elif text == "any":
172 text = self.tr("any")
173 elif text is None:
174 text = ""
175 if forUrl:
176 if not isinstance(text, basestring) or \
177 not text.startswith(("http://", "https://", "ftp://")):
178 # ignore if the schema is not one of the listed ones
179 text = ""
180
181 return text
182
183 def __formatUploadDate(self, datetime):
184 """
185 Private method to format the upload date.
186
187 @param datetime upload date and time (xmlrpc.DateTime)
188 @return formatted date string (string)
189 """
190 date = datetime.value.split("T")[0]
191 return "{0}-{1}-{2}".format(date[:4], date[4:6], date[6:])
192
193 def __formatSize(self, size):
194 """
195 Private slot to format the size.
196
197 @param size size to be formatted (integer)
198 @return formatted size (string)
199 """
200 unit = ""
201 if size < 1024:
202 unit = self.tr("B")
203 elif size < 1024 * 1024:
204 size /= 1024
205 unit = self.tr("KB")
206 elif size < 1024 * 1024 * 1024:
207 size /= 1024 * 1024
208 unit = self.tr("MB")
209 else:
210 size /= 1024 * 1024 * 1024
211 unit = self.tr("GB")
212 return self.tr("{0:.1f} {1}", "value, unit").format(size, unit)

eric ide

mercurial