Skip to content

Commit 52a4752

Browse files
committed
chore: simplify format flags handling
Move merging to a single location where errors can be handled consistently. See #17816
1 parent 4ed5087 commit 52a4752

File tree

5 files changed

+62
-52
lines changed

5 files changed

+62
-52
lines changed

weblate/formats/base.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from django.http import HttpResponse
1616
from django.utils.functional import cached_property
1717
from django.utils.translation import gettext
18+
from pyparsing import ParseException
1819
from translate.misc.multistring import multistring
1920
from translate.storage.base import TranslationStore as TranslateToolkitStore
2021
from translate.storage.base import TranslationUnit as TranslateToolkitUnit
@@ -28,9 +29,10 @@
2829
from weblate.utils.state import STATE_EMPTY, STATE_TRANSLATED
2930

3031
if TYPE_CHECKING:
31-
from collections.abc import Callable, Iterator, Sequence
32+
from collections.abc import Callable, Generator, Iterator, Sequence
3233

3334
from django_stubs_ext import StrOrPromise
35+
from lxml import etree
3436

3537
from weblate.trans.file_format_params import FileFormatParams
3638
from weblate.trans.models import Component, Translation, Unit
@@ -153,6 +155,8 @@ class TranslationUnit:
153155
parent: TranslationFormat
154156
mainunit: InnerUnit
155157
empty_unit_ok: ClassVar[bool] = False
158+
remove_flags: ClassVar[list[str]] = []
159+
add_flags: ClassVar[list[str]] = []
156160

157161
def __init__(
158162
self,
@@ -199,17 +203,30 @@ def locations(self) -> str:
199203
"""Return comma separated list of locations."""
200204
return ""
201205

202-
@cached_property
203-
def flags(self) -> Flags:
204-
"""Return flags or typecomments from units."""
205-
flags = Flags()
206+
def get_extra_flags(self) -> Generator[str | etree._Element | Flags]:
206207
# add default flags based location extensions
207208
for location in self.locations.split(","):
208209
_, extension = os.path.splitext(location.split(":")[0].strip())
209210
if extension == ".rst":
210-
flags.merge("rst-text")
211+
yield "rst-text"
211212
elif extension in {".md", ".markdown"}:
212-
flags.merge("md-text")
213+
yield "md-text"
214+
yield from self.add_flags
215+
216+
@cached_property
217+
def flags(self) -> Flags:
218+
"""Return flags or typecomments from units."""
219+
flags = Flags()
220+
for extra in self.get_extra_flags():
221+
try:
222+
flags.merge(extra)
223+
except (ParseException, ValueError) as error:
224+
msg = f"Could not parse flags: {extra}: {error}"
225+
raise ValueError(msg) from error
226+
227+
for remove in self.remove_flags:
228+
flags.remove(remove)
229+
213230
return flags
214231

215232
@cached_property

weblate/formats/convert.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ def source(self):
8484

8585

8686
class ConvertXliffUnit(XliffUnit):
87+
remove_flags: ClassVar[list[str]] = ["xml-text"]
88+
8789
def is_fuzzy(self, fallback=False):
8890
"""Check whether unit needs editing."""
8991
return fallback
@@ -98,12 +100,6 @@ def is_translated(self):
98100
return self.has_translation()
99101
return self.unit is not None
100102

101-
@cached_property
102-
def flags(self):
103-
flags = super().flags
104-
flags.remove("xml-text")
105-
return flags
106-
107103

108104
class ConvertFormat(TranslationFormat):
109105
"""

weblate/formats/multi.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@
1717
from .ttkit import CSVFormat
1818

1919
if TYPE_CHECKING:
20+
from collections.abc import Generator
21+
22+
from lxml import etree
2023
from translate.storage.base import TranslationStore
2124
from translate.storage.base import TranslationUnit as TranslateToolkitUnit
2225

26+
from weblate.checks.flags import Flags
27+
2328

2429
class MultiUnit(TranslationUnit):
2530
units: list[TranslationUnit]
@@ -105,12 +110,11 @@ def set_state(self, state) -> None:
105110
for unit in self.units:
106111
unit.set_state(state)
107112

108-
@cached_property
109-
def flags(self):
110-
flags = super().flags
113+
def get_extra_flags(self) -> Generator[str | etree._Element | Flags]:
114+
yield from super().get_extra_flags()
115+
111116
for unit in self.units:
112-
flags.merge(unit.flags)
113-
return flags
117+
yield unit.flags
114118

115119
def has_unit(self) -> bool:
116120
return all(unit.has_unit() for unit in self.units)

weblate/formats/ttkit.py

Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from django.utils.translation import gettext, gettext_lazy
2323
from lxml import etree
2424
from lxml.etree import XMLSyntaxError
25-
from pyparsing import ParseException
2625
from translate.misc import quote
2726
from translate.misc.multistring import multistring
2827
from translate.misc.xml_helpers import setXMLspace
@@ -74,7 +73,7 @@
7473
)
7574

7675
if TYPE_CHECKING:
77-
from collections.abc import Callable
76+
from collections.abc import Callable, Generator
7877

7978
from translate.storage.base import TranslationUnit as TranslateToolkitUnit
8079

@@ -180,19 +179,17 @@ def set_state(self, state) -> None:
180179
if hasattr(self.unit, "markapproved"):
181180
self.unit.markapproved(state == STATE_APPROVED)
182181

183-
@cached_property
184-
def flags(self):
182+
def get_extra_flags(self) -> Generator[str | etree._Element | Flags]:
185183
"""
186184
Return flags from unit.
187185
188-
We currently extract maxwidth attribute.
186+
We currently extract from XML.
189187
"""
190-
flags = super().flags
188+
yield from super().get_extra_flags()
191189
if hasattr(self.unit, "xmlelement"):
192-
flags.merge(self.unit.xmlelement)
190+
yield self.unit.xmlelement
193191
if self.template is not None and hasattr(self.template, "xmlelement"):
194-
flags.merge(self.template.xmlelement)
195-
return flags
192+
yield self.template.xmlelement
196193

197194
def clone_template(self) -> None:
198195
super().clone_template()
@@ -577,6 +574,9 @@ def target(self):
577574
class PoUnit(TTKitUnit):
578575
"""Wrapper for gettext PO unit."""
579576

577+
# Fuzzy flag is not useful, it is exposed as state instead
578+
remove_flags: ClassVar[list[str]] = ["fuzzy"]
579+
580580
def set_state(self, state) -> None:
581581
"""Set fuzzy /approved flag on translated unit."""
582582
super().set_state(state)
@@ -585,17 +585,14 @@ def set_state(self, state) -> None:
585585
self.unit.prev_msgid_plural = []
586586
self.unit.prev_msgctxt = []
587587

588-
@cached_property
589-
def flags(self):
590-
"""Return flags or typecomments from units."""
591-
flags = super().flags
592-
try:
593-
flags.merge(Flags(*self.mainunit.typecomments))
594-
except ParseException as error:
595-
msg = f"Could not parse flags: {self.mainunit.typecomments!r}: {error}"
596-
raise ValueError(msg) from error
597-
flags.remove({"fuzzy"})
598-
return flags
588+
def get_extra_flags(self) -> Generator[str | etree._Element | Flags]:
589+
"""
590+
Return flags from unit.
591+
592+
We currently extract from typecomments.
593+
"""
594+
yield from super().get_extra_flags()
595+
yield from self.mainunit.typecomments
599596

600597
@cached_property
601598
def previous_source(self):
@@ -847,6 +844,8 @@ def target(self):
847844
class RichXliffUnit(XliffUnit):
848845
"""Wrapper unit for XLIFF with XML elements."""
849846

847+
add_flags: ClassVar[list[str]] = ["xml-text"]
848+
850849
@cached_property
851850
def source(self):
852851
"""Return source string from a Translate Toolkit unit."""
@@ -871,12 +870,6 @@ def target(self):
871870

872871
return rich_to_xliff_string(self.unit.rich_target)
873872

874-
@cached_property
875-
def flags(self):
876-
flags = super().flags
877-
flags.merge("xml-text")
878-
return flags
879-
880873
def set_target(self, target: str | list[str]) -> None:
881874
"""Set translation unit target."""
882875
self._invalidate_target()
@@ -1021,7 +1014,7 @@ def flags(self):
10211014
# WebExtension placeholders
10221015
placeholder_ids = [f"${key.upper()}$" for key in placeholders]
10231016
flags.merge("case-insensitive")
1024-
flags.merge(f"placeholders:{Flags.format_flag(placeholder_ids)}")
1017+
flags.set_value("placeholders", Flags.format_flag(placeholder_ids))
10251018
return flags
10261019

10271020

weblate/formats/txt.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
from weblate.utils.errors import report_error
2525

2626
if TYPE_CHECKING:
27-
from collections.abc import Callable
27+
from collections.abc import Callable, Generator
2828

29+
from lxml import etree
30+
31+
from weblate.checks.flags import Flags
2932
from weblate.trans.file_format_params import FileFormatParams
3033

3134

@@ -177,13 +180,10 @@ def context(self):
177180
"""Return context of message."""
178181
return self.mainunit.location
179182

180-
@cached_property
181-
def flags(self):
182-
"""Return flags from unit."""
183-
flags = super().flags
183+
def get_extra_flags(self) -> Generator[str | etree._Element | Flags]:
184+
yield from super().get_extra_flags()
184185
if self.mainunit.flags:
185-
flags.merge(self.mainunit.flags)
186-
return flags
186+
yield self.mainunit.flags
187187

188188
def set_target(self, target: str | list[str]) -> None:
189189
"""Set translation unit target."""

0 commit comments

Comments
 (0)