Plugins/UiExtensionPlugins/PipInterface/PipPackageDetailsDialog.py

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

eric ide

mercurial