Coverage for app/venv/lib/python3.14/site-packages/weblate/sitemaps.py: 67%

51 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 

5from itertools import chain 

6from typing import NoReturn 

7 

8from django.contrib.sitemaps import Sitemap 

9from django.urls import reverse 

10 

11from weblate.trans.models import Change, Component, Project, Translation 

12from weblate.utils.stats import prefetch_stats 

13 

14 

15class PagesSitemap(Sitemap): 

16 def items(self): 

17 return ( 

18 ("/", 1.0, "daily"), 

19 ("/about/", 0.4, "weekly"), 

20 ("/keys/", 0.4, "weekly"), 

21 ) 

22 

23 def location(self, obj): 

24 return obj[0] 

25 

26 def lastmod(self, item): 

27 try: 

28 return Change.objects.values_list("timestamp", flat=True).latest( 

29 "timestamp" 

30 ) 

31 except Change.DoesNotExist: 

32 return None 

33 

34 def priority(self, item): 

35 return item[1] 

36 

37 def changefreq(self, item): 

38 return item[2] 

39 

40 

41class WeblateSitemap(Sitemap): 

42 priority = 0.0 

43 changefreq = None 

44 

45 def items(self) -> NoReturn: 

46 raise NotImplementedError 

47 

48 def lastmod(self, item): 

49 return item.stats.last_changed 

50 

51 def get_latest_lastmod(self) -> None: 

52 # Finding latest lastmod is expensive as it needs fetching 

53 # stats for all objects 

54 return None 

55 

56 

57class ProjectSitemap(WeblateSitemap): 

58 priority = 0.8 

59 

60 def items(self): 

61 return prefetch_stats( 

62 Project.objects.filter(access_control__lt=Project.ACCESS_PRIVATE).order_by( 

63 "id" 

64 ) 

65 ) 

66 

67 

68class ComponentSitemap(WeblateSitemap): 

69 priority = 0.6 

70 

71 def items(self): 

72 return prefetch_stats( 

73 Component.objects.prefetch_related("project") 

74 .filter(project__access_control__lt=Project.ACCESS_PRIVATE) 

75 .order_by("id") 

76 ) 

77 

78 

79class TranslationSitemap(WeblateSitemap): 

80 priority = 0.2 

81 

82 def items(self): 

83 return prefetch_stats( 

84 Translation.objects.prefetch_related( 

85 "component", 

86 "component__project", 

87 "language", 

88 ) 

89 .filter(component__project__access_control__lt=Project.ACCESS_PRIVATE) 

90 .order_by("id") 

91 ) 

92 

93 

94class EngageSitemap(ProjectSitemap): 

95 """Wrapper around ProjectSitemap to point to engage page.""" 

96 

97 priority = 1.0 

98 

99 def location(self, obj): 

100 return reverse("engage", kwargs={"path": obj.get_url_path()}) 

101 

102 

103class EngageLangSitemap(EngageSitemap): 

104 """Wrapper to generate sitemap for all per language engage pages.""" 

105 

106 priority = 0.9 

107 

108 def items(self): 

109 """Return list of existing project, language tuples.""" 

110 projects = ( 

111 Project.objects.filter(access_control__lt=Project.ACCESS_PRIVATE) 

112 .order_by("id") 

113 .prefetch_languages() 

114 ) 

115 return prefetch_stats( 

116 chain.from_iterable( 

117 project.project_languages.preload() for project in projects 

118 ) 

119 ) 

120 

121 

122SITEMAPS = { 

123 "project": ProjectSitemap(), 

124 "engage": EngageSitemap(), 

125 "engagelang": EngageLangSitemap(), 

126 "component": ComponentSitemap(), 

127 "translation": TranslationSitemap(), 

128 "pages": PagesSitemap(), 

129}