Coverage for app/venv/lib/python3.14/site-packages/weblate/trans/models/componentlist.py: 72%

48 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 07:15 +0000

1# Copyright © Michal Čihař <michal@weblate.org> 

2# 

3# SPDX-License-Identifier: GPL-3.0-or-later 

4 

5"""Components list.""" 

6 

7from __future__ import annotations 

8 

9import re 

10from typing import TYPE_CHECKING 

11 

12from django.db import models 

13from django.urls import reverse 

14from django.utils.translation import gettext_lazy 

15 

16from weblate.trans.fields import RegexField 

17from weblate.trans.mixins import CacheKeyMixin 

18from weblate.utils.stats import ComponentListStats 

19 

20if TYPE_CHECKING: 20 ↛ 21line 20 didn't jump to line 21 because the condition on line 20 was never true

21 from weblate.trans.models.translation import Translation 

22 

23 

24class ComponentListQuerySet(models.QuerySet): 

25 def order(self): 

26 return self.order_by("name") 

27 

28 

29class ComponentList(models.Model, CacheKeyMixin): 

30 name = models.CharField( 

31 verbose_name=gettext_lazy("Component list name"), 

32 max_length=100, 

33 unique=True, 

34 help_text=gettext_lazy("Display name"), 

35 ) 

36 

37 slug = models.SlugField( 

38 verbose_name=gettext_lazy("URL slug"), 

39 db_index=True, 

40 unique=True, 

41 max_length=100, 

42 help_text=gettext_lazy("Name used in URLs and filenames."), 

43 ) 

44 show_dashboard = models.BooleanField( 

45 verbose_name=gettext_lazy("Show on dashboard"), 

46 default=True, 

47 db_index=True, 

48 help_text=gettext_lazy( 

49 "When enabled this component list will be shown as a tab on the dashboard" 

50 ), 

51 ) 

52 

53 components = models.ManyToManyField("trans.Component", blank=True) 

54 

55 # Used on dashboard 

56 translations: list[Translation] 

57 

58 objects = ComponentListQuerySet.as_manager() 

59 

60 class Meta: 

61 verbose_name = "Component list" 

62 verbose_name_plural = "Component lists" 

63 

64 def __str__(self) -> str: 

65 return self.name 

66 

67 def __init__(self, *args, **kwargs) -> None: 

68 super().__init__(*args, **kwargs) 

69 self.stats = ComponentListStats(self) 

70 

71 def get_absolute_url(self) -> str: 

72 return reverse("component-list", kwargs={"name": self.slug}) 

73 

74 def tab_slug(self): 

75 return "list-" + self.slug 

76 

77 

78class AutoComponentList(models.Model): 

79 project_match = RegexField( 

80 verbose_name=gettext_lazy("Project regular expression"), 

81 max_length=200, 

82 default="^$", 

83 help_text=gettext_lazy( 

84 "Regular expression which is used to match project slug." 

85 ), 

86 ) 

87 component_match = RegexField( 

88 verbose_name=gettext_lazy("Component regular expression"), 

89 max_length=200, 

90 default="^$", 

91 help_text=gettext_lazy( 

92 "Regular expression which is used to match component slug." 

93 ), 

94 ) 

95 componentlist = models.ForeignKey( 

96 ComponentList, 

97 verbose_name=gettext_lazy("Component list to assign"), 

98 on_delete=models.deletion.CASCADE, 

99 ) 

100 

101 class Meta: 

102 verbose_name = "Automatic component list assignment" 

103 verbose_name_plural = "Automatic component list assignments" 

104 

105 def __str__(self) -> str: 

106 return self.componentlist.name 

107 

108 def check_match(self, component) -> None: 

109 if not re.match(self.project_match, component.project.slug): 

110 return 

111 if not re.match(self.component_match, component.slug): 

112 return 

113 self.componentlist.components.add(component)