11626.3.7
by Curtis Hovey
Fixed copyright dates. |
1 |
# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
|
8687.15.18
by Karl Fogel
Add the copyright header block to files under lib/canonical/. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
3 |
|
4 |
"""View class for requesting translation exports."""
|
|
5 |
||
6 |
__metaclass__ = type |
|
7 |
__all__ = ['BaseExportView'] |
|
8 |
||
4767.9.26
by Carlos Perello Marin
Applied review comments |
9 |
|
10315.2.1
by Jeroen Vermeulen
Show export queue status on export request pages. |
10 |
from datetime import timedelta |
11 |
||
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
12 |
from zope.component import getUtility |
13 |
||
14600.1.12
by Curtis Hovey
Move i18n to lp. |
14 |
from lp import _ |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
15 |
from canonical.launchpad.webapp import ( |
16 |
canonical_url, |
|
17 |
LaunchpadView, |
|
18 |
)
|
|
11626.3.2
by Curtis Hovey
Move tales gto lp.app. |
19 |
from lp.app.browser.tales import DurationFormatterAPI |
11382.6.34
by Gavin Panella
Reformat imports in all files touched so far. |
20 |
from lp.services.propertycache import cachedproperty |
11882.1.1
by Jeroen Vermeulen
Independence for IHasTranslationTemplates\! |
21 |
from lp.translations.interfaces.hastranslationtemplates import ( |
22 |
IHasTranslationTemplates, |
|
23 |
)
|
|
14550.1.1
by Steve Kowalik
Run format-imports over lib/lp and lib/canonical/launchpad |
24 |
from lp.translations.interfaces.poexportrequest import IPOExportRequestSet |
8751.1.1
by Danilo Šegan
Store migration changes so far. |
25 |
from lp.translations.interfaces.translationexporter import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
26 |
ITranslationExporter, |
27 |
)
|
|
8751.1.1
by Danilo Šegan
Store migration changes so far. |
28 |
from lp.translations.interfaces.translationfileformat import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
29 |
TranslationFileFormat, |
30 |
)
|
|
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
31 |
|
32 |
||
33 |
class BaseExportView(LaunchpadView): |
|
34 |
"""Base class for PO export views."""
|
|
35 |
||
4767.9.26
by Carlos Perello Marin
Applied review comments |
36 |
@cachedproperty
|
37 |
def uses_translations(self): |
|
8778.3.1
by Jeroen Vermeulen
Ported from old branch, with lots of changes. |
38 |
return self.context.has_current_translation_templates |
4767.9.26
by Carlos Perello Marin
Applied review comments |
39 |
|
10315.2.1
by Jeroen Vermeulen
Show export queue status on export request pages. |
40 |
@property
|
41 |
def export_queue_status(self): |
|
42 |
"""Summary of queue status."""
|
|
43 |
queue_size = self.request_set.entry_count |
|
44 |
estimated_backlog = self.request_set.estimateBacklog() |
|
45 |
||
46 |
size_text = self.describeQueueSize(queue_size) |
|
47 |
backlog_text = self.describeBacklog(estimated_backlog) |
|
48 |
||
49 |
return " ".join((size_text, backlog_text)) |
|
50 |
||
51 |
def describeQueueSize(self, queue_size): |
|
52 |
"""Return string describing the given queue size."""
|
|
53 |
if queue_size == 0: |
|
54 |
return "The export queue is currently empty." |
|
55 |
elif queue_size == 1: |
|
56 |
return "There is 1 file request on the export queue." |
|
57 |
else: |
|
58 |
return ( |
|
59 |
"There are %d file requests on the export queue." |
|
60 |
% queue_size) |
|
61 |
||
62 |
def describeBacklog(self, estimated_backlog): |
|
63 |
"""Return string describing the current export backlog."""
|
|
10315.2.8
by Jeroen Vermeulen
Review chang. |
64 |
threshold = timedelta(minutes=10) |
65 |
if estimated_backlog is None or estimated_backlog < threshold: |
|
10315.2.1
by Jeroen Vermeulen
Show export queue status on export request pages. |
66 |
return "" |
67 |
||
68 |
formatter = DurationFormatterAPI(estimated_backlog) |
|
69 |
time_string = formatter.approximateduration() |
|
70 |
return "The backlog is approximately %s." % time_string |
|
71 |
||
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
72 |
def getDefaultFormat(self): |
8777.5.3
by Danilo Šegan
Some cleanups in BaseExport view. |
73 |
"""Overridable: return default file format to use for the export."""
|
8777.5.1
by Danilo Šegan
Move shared methods into BaseExportView. |
74 |
if not IHasTranslationTemplates.providedBy(self.context): |
75 |
raise NotImplementedError( |
|
76 |
'Subclass not implementing `IHasTranslationsTemplates` '
|
|
77 |
'interface. Either override getDefaultFormat implementation '
|
|
78 |
'or implement `IHasTranslationsTemplates`.') |
|
79 |
||
80 |
templates = self.context.getCurrentTranslationTemplates() |
|
81 |
if not bool(templates.any()): |
|
82 |
return None |
|
12622.6.27
by Henning Eggers
Reintroduced shortlist. |
83 |
formats = self.context.getTranslationTemplateFormats() |
8777.5.1
by Danilo Šegan
Move shared methods into BaseExportView. |
84 |
format = formats[0] |
85 |
if len(formats) > 1: |
|
86 |
self.request.response.addInfoNotification( |
|
87 |
"This package has templates with different native "
|
|
88 |
"file formats. If you proceed, all translations will be "
|
|
89 |
"exported in the single format you specify.") |
|
90 |
return format |
|
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
91 |
|
92 |
def processForm(self): |
|
8777.5.3
by Danilo Šegan
Some cleanups in BaseExport view. |
93 |
"""Return templates and translations requested to be exported.
|
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
94 |
|
8777.5.3
by Danilo Šegan
Some cleanups in BaseExport view. |
95 |
Overridable in a child class. Must do one of:
|
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
96 |
a. Add an error notification to the page and return `None`
|
8777.5.6
by Danilo Šegan
Apply review Brad's comments. |
97 |
b. Return a tuple of two iterables or None, of requested templates
|
8816.1.2
by Danilo Šegan
Apply noodles' review comments. |
98 |
and of requested pofiles IDs.
|
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
99 |
c. Redirect and return `None`.
|
100 |
"""
|
|
8777.5.3
by Danilo Šegan
Some cleanups in BaseExport view. |
101 |
if not IHasTranslationTemplates.providedBy(self.context): |
102 |
raise NotImplementedError( |
|
103 |
'Subclass not implementing `IHasTranslationsTemplates` '
|
|
104 |
'interface. Either override getDefaultFormat implementation '
|
|
105 |
'or implement `IHasTranslationsTemplates`.') |
|
106 |
||
8816.1.2
by Danilo Šegan
Apply noodles' review comments. |
107 |
translation_templates_ids = ( |
8816.1.1
by Danilo Šegan
Return a ResultSet over IDs instead of over full objects in BaseExportView.processForm. |
108 |
self.context.getCurrentTranslationTemplates(just_ids=True)) |
8816.1.2
by Danilo Šegan
Apply noodles' review comments. |
109 |
pofiles_ids = self.context.getCurrentTranslationFiles(just_ids=True) |
110 |
if not bool(pofiles_ids.any()): |
|
111 |
pofiles_ids = None |
|
112 |
return (translation_templates_ids, pofiles_ids) |
|
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
113 |
|
7675.1015.19
by Henning Eggers
Fixed the bug. |
114 |
def getExportFormat(self): |
115 |
"""Optional overridable: The requested export format."""
|
|
116 |
return self.request.form.get("format") |
|
7667.11.2
by Henning Eggers
PO export form completed. |
117 |
|
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
118 |
def initialize(self): |
119 |
self.request_set = getUtility(IPOExportRequestSet) |
|
4940.1.8
by Jeroen Vermeulen
Must initialize default_format even for POSTs. |
120 |
|
121 |
# Ask our derived class to figure out the default file format for this
|
|
122 |
# export. We do that here because the method may issue warnings,
|
|
123 |
# which must be attached to our response early on.
|
|
124 |
self.default_format = self.getDefaultFormat() |
|
125 |
||
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
126 |
if self.request.method != "POST": |
127 |
return
|
|
128 |
||
129 |
bad_format_message = _("Please select a valid format for download.") |
|
7675.1015.19
by Henning Eggers
Fixed the bug. |
130 |
format_name = self.getExportFormat() |
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
131 |
if format_name is None: |
132 |
self.request.response.addErrorNotification(bad_format_message) |
|
133 |
return
|
|
134 |
try: |
|
135 |
format = TranslationFileFormat.items[format_name] |
|
136 |
except KeyError: |
|
137 |
self.request.response.addErrorNotification(bad_format_message) |
|
138 |
return
|
|
139 |
||
140 |
requested_files = self.processForm() |
|
141 |
if requested_files is None: |
|
142 |
return
|
|
143 |
||
144 |
templates, pofiles = requested_files |
|
145 |
if not templates and not pofiles: |
|
146 |
self.request.response.addErrorNotification( |
|
147 |
"Please select at least one translation or template.") |
|
148 |
else: |
|
4940.1.9
by Jeroen Vermeulen
Cosmetic. |
149 |
self.request_set.addRequest(self.user, templates, pofiles, format) |
4673.6.6
by Jeroen Vermeulen
Changes based on ongoing review. |
150 |
self.nextURL() |
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
151 |
|
152 |
def nextURL(self): |
|
153 |
self.request.response.addInfoNotification(_( |
|
154 |
"Your request has been received. Expect to receive an email "
|
|
155 |
"shortly.")) |
|
11388.1.11
by Tim Penhey
Yet more explicit translations references. |
156 |
self.request.response.redirect( |
157 |
canonical_url(self.context, rootsite='translations')) |
|
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
158 |
|
159 |
def formats(self): |
|
160 |
"""Return a list of formats available for translation exports."""
|
|
161 |
||
162 |
class BrowserFormat: |
|
11626.3.10
by Curtis Hovey
Hush lints epic complaints about the changes files. |
163 |
|
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
164 |
def __init__(self, title, value, is_default=False): |
165 |
self.title = title |
|
166 |
self.value = value |
|
167 |
self.is_default = is_default |
|
168 |
||
4769.2.17
by Danilo Šegan
Final review comments from Brad, Tom, Bjorn. |
169 |
translation_exporter = getUtility(ITranslationExporter) |
170 |
exporters = translation_exporter.getExportersForSupportedFileFormat( |
|
4940.1.7
by Jeroen Vermeulen
Show warning if source package has translation templates in multiple formats. |
171 |
self.default_format) |
4769.2.8
by Danilo Šegan
Fix supported formats. |
172 |
for exporter in exporters: |
173 |
format = exporter.format |
|
4940.1.7
by Jeroen Vermeulen
Show warning if source package has translation templates in multiple formats. |
174 |
if format == self.default_format: |
4769.2.11
by Danilo Šegan
Implemented review comments from Tom Berger. |
175 |
is_default = True |
176 |
else: |
|
177 |
is_default = False |
|
4673.6.1
by Jeroen Vermeulen
Provide download of all translations for a productseries. |
178 |
yield BrowserFormat(format.title, format.name, is_default) |