9
from storm.locals import ClassAlias, Store
9
from storm.expr import (
16
from storm.locals import (
22
from lp.registry.model.distroseries import DistroSeries
23
from lp.registry.model.packaging import Packaging
24
from lp.registry.model.productseries import ProductSeries
12
25
from lp.translations.model.potemplate import POTemplate
13
26
from lp.translations.model.translationtemplateitem import (
14
27
TranslationTemplateItem,
18
class TranslationSplitter:
19
"""Split translations for a productseries, sourcepackage pair.
21
If a productseries and sourcepackage were linked in error, and then
22
unlinked, they may still share some translations. This class breaks those
26
def __init__(self, productseries, sourcepackage):
29
:param productseries: The `ProductSeries` to split from.
30
:param sourcepackage: The `SourcePackage` to split from.
32
self.productseries = productseries
33
self.sourcepackage = sourcepackage
36
"""Provide tuples of upstream, ubuntu for each shared POTMsgSet."""
37
store = Store.of(self.productseries)
38
UpstreamItem = ClassAlias(TranslationTemplateItem, 'UpstreamItem')
39
UpstreamTemplate = ClassAlias(POTemplate, 'UpstreamTemplate')
40
UbuntuItem = ClassAlias(TranslationTemplateItem, 'UbuntuItem')
41
UbuntuTemplate = ClassAlias(POTemplate, 'UbuntuTemplate')
43
(UpstreamItem, UbuntuItem),
44
UpstreamItem.potmsgsetID == UbuntuItem.potmsgsetID,
45
UbuntuItem.potemplateID == UbuntuTemplate.id,
46
UbuntuTemplate.sourcepackagenameID ==
47
self.sourcepackage.sourcepackagename.id,
48
UbuntuTemplate.distroseriesID ==
49
self.sourcepackage.distroseries.id,
50
UpstreamItem.potemplateID == UpstreamTemplate.id,
51
UpstreamTemplate.productseriesID == self.productseries.id,
31
class TranslationSplitterBase:
32
"""Base class for translation splitting jobs."""
55
35
def splitPOTMsgSet(ubuntu_item):
86
66
"""Split the translations for the ProductSeries and SourcePackage."""
87
67
logger = logging.getLogger()
88
68
shared = enumerate(self.findShared(), 1)
89
70
for num, (upstream_item, ubuntu_item) in shared:
90
71
self.splitPOTMsgSet(ubuntu_item)
91
72
self.migrateTranslations(upstream_item.potmsgset, ubuntu_item)
93
74
logger.info('%d entries split. Committing...', num)
94
75
transaction.commit()
78
if total % 100 != 0 or total == 0:
80
logger.info('%d entries split.', total)
83
class TranslationSplitter(TranslationSplitterBase):
84
"""Split translations for a productseries, sourcepackage pair.
86
If a productseries and sourcepackage were linked in error, and then
87
unlinked, they may still share some translations. This class breaks those
91
def __init__(self, productseries, sourcepackage):
94
:param productseries: The `ProductSeries` to split from.
95
:param sourcepackage: The `SourcePackage` to split from.
97
self.productseries = productseries
98
self.sourcepackage = sourcepackage
100
def findShared(self):
101
"""Provide tuples of upstream, ubuntu for each shared POTMsgSet."""
102
store = Store.of(self.productseries)
103
UpstreamItem = ClassAlias(TranslationTemplateItem, 'UpstreamItem')
104
UpstreamTemplate = ClassAlias(POTemplate, 'UpstreamTemplate')
105
UbuntuItem = ClassAlias(TranslationTemplateItem, 'UbuntuItem')
106
UbuntuTemplate = ClassAlias(POTemplate, 'UbuntuTemplate')
108
(UpstreamItem, UbuntuItem),
109
UpstreamItem.potmsgsetID == UbuntuItem.potmsgsetID,
110
UbuntuItem.potemplateID == UbuntuTemplate.id,
111
UbuntuTemplate.sourcepackagenameID ==
112
self.sourcepackage.sourcepackagename.id,
113
UbuntuTemplate.distroseriesID ==
114
self.sourcepackage.distroseries.id,
115
UpstreamItem.potemplateID == UpstreamTemplate.id,
116
UpstreamTemplate.productseriesID == self.productseries.id,
120
class TranslationTemplateSplitter(TranslationSplitterBase):
121
"""Split translations for an extracted potemplate.
123
When a POTemplate is removed from a set of sharing templates,
124
it keeps sharing POTMsgSets with other templates. This class
125
removes those associations.
128
def __init__(self, potemplate):
131
:param potemplate: The `POTemplate` to sanitize.
133
self.potemplate = potemplate
135
def findShared(self):
136
"""Provide tuples of (other, this) items for each shared POTMsgSet.
138
Only return those that are shared but shouldn't be because they
139
are now in non-sharing templates.
141
store = Store.of(self.potemplate)
142
ThisItem = ClassAlias(TranslationTemplateItem, 'ThisItem')
143
OtherItem = ClassAlias(TranslationTemplateItem, 'OtherItem')
144
OtherTemplate = ClassAlias(POTemplate, 'OtherTemplate')
148
Join(OtherItem, OtherItem.potemplateID == OtherTemplate.id),
150
And(ThisItem.potmsgsetID == OtherItem.potmsgsetID,
151
ThisItem.potemplateID == self.potemplate.id)),
154
if self.potemplate.productseries is not None:
155
# If the template is now in a product, we look for all
156
# effectively sharing templates that are in *different*
157
# products, or that are in a sourcepackage which is not
158
# linked (through Packaging table) with this product.
159
ps = self.potemplate.productseries
160
productseries_join = LeftJoin(
162
ProductSeries.id == OtherTemplate.productseriesID)
163
packaging_join = LeftJoin(
165
And(Packaging.productseriesID == ps.id,
166
(Packaging.sourcepackagenameID ==
167
OtherTemplate.sourcepackagenameID),
168
Packaging.distroseriesID == OtherTemplate.distroseriesID
170
tables.extend([productseries_join, packaging_join])
171
# Template should not be sharing if...
173
# The name is different, or...
174
OtherTemplate.name != self.potemplate.name,
175
# It's in a different product, or...
176
And(Not(ProductSeries.id == None),
177
ProductSeries.productID != ps.productID),
178
# There is no link between this product series and
179
# a source package the template is in.
180
And(Not(OtherTemplate.distroseriesID == None),
181
Packaging.id == None))
183
# If the template is now in a source package, we look for all
184
# effectively sharing templates that are in *different*
185
# distributions or source packages, or that are in a product
186
# which is not linked with this source package.
187
ds = self.potemplate.distroseries
188
spn = self.potemplate.sourcepackagename
189
distroseries_join = LeftJoin(
191
DistroSeries.id == OtherTemplate.distroseriesID)
192
packaging_join = LeftJoin(
194
And(Packaging.distroseriesID == ds.id,
195
Packaging.sourcepackagenameID == spn.id,
196
Packaging.productseriesID == OtherTemplate.productseriesID
198
tables.extend([distroseries_join, packaging_join])
199
# Template should not be sharing if...
201
# The name is different, or...
202
OtherTemplate.name != self.potemplate.name,
203
# It's in a different distribution or source package, or...
204
And(Not(DistroSeries.id == None),
205
Or(DistroSeries.distributionID != ds.distributionID,
206
OtherTemplate.sourcepackagenameID != spn.id)),
207
# There is no link between this source package and
208
# a product the template is in.
209
And(Not(OtherTemplate.productseriesID == None),
210
Packaging.id == None))
212
return store.using(*tables).find(
213
(OtherItem, ThisItem),
214
OtherTemplate.id != self.potemplate.id,