Coverage for fastblocks/adapters/sitemap/native.py: 0%
71 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-21 04:50 -0700
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-21 04:50 -0700
1"""FastBlocks Native Sitemap Adapter.
3Automatic route-based sitemap generation using FastBlocks routing system
4with enhanced caching, filtering, and debugging capabilities.
5"""
7import re
8from contextlib import suppress
9from uuid import UUID
11from acb.adapters import AdapterStatus
12from acb.debug import debug
13from acb.depends import depends
15from ._base import SitemapBase, SitemapBaseSettings
16from .core import BaseSitemap, SitemapApp
19class NativeSitemapSettings(SitemapBaseSettings):
20 pass
23class NativeSitemap(BaseSitemap[str], SitemapBase):
24 sitemap: SitemapApp | None = None
26 @depends.inject
27 def items(self) -> list[str]:
28 try:
29 routes_adapter = depends.get("routes")
30 if not hasattr(routes_adapter, "routes"):
31 debug("NativeSitemap: No routes adapter found")
32 return []
33 route_paths = [r.path for r in routes_adapter.routes]
34 debug(f"NativeSitemap: Found {len(route_paths)} routes")
35 filtered_paths = self._filter_routes(route_paths)
36 debug(f"NativeSitemap: Filtered to {len(filtered_paths)} routes")
38 return filtered_paths
39 except Exception as e:
40 debug(f"NativeSitemap: Error getting routes: {e}")
41 return []
43 def _filter_routes(self, routes: list[str]) -> list[str]:
44 strategy_options = self.config.strategy_options
45 include_patterns = strategy_options.get("include_patterns", [])
46 exclude_patterns = strategy_options.get("exclude_patterns", [])
47 filtered = routes[:]
48 for pattern in exclude_patterns:
49 try:
50 regex = re.compile(
51 pattern
52 ) # REGEX OK: Dynamic user patterns for route filtering
53 filtered = [
54 r for r in filtered if not regex.match(r)
55 ] # REGEX OK: Pattern matching for route filtering
56 except re.error as e:
57 debug(f"NativeSitemap: Invalid exclude pattern '{pattern}': {e}")
58 if include_patterns:
59 included = []
60 for pattern in include_patterns:
61 try:
62 regex = re.compile(
63 pattern
64 ) # REGEX OK: Dynamic user patterns for route filtering
65 included.extend(
66 [r for r in filtered if regex.match(r)]
67 ) # REGEX OK: Pattern matching for route filtering
68 except re.error as e:
69 debug(f"NativeSitemap: Invalid include pattern '{pattern}': {e}")
70 filtered = list(set(included))
72 return filtered
74 def location(self, item: str) -> str:
75 return item
77 def changefreq(self, item: str) -> str:
78 return self.config.change_freq
80 def priority(self, item: str) -> float:
81 if item == "/":
82 return 1.0
83 segments = len([s for s in item.split("/") if s])
84 if segments == 1:
85 return 0.8
86 elif segments == 2:
87 return 0.6
88 else:
89 return 0.4
91 async def init(self) -> None:
92 if not self.config.domain:
93 msg = "domain must be set in sitemap settings"
94 raise ValueError(msg)
95 self.sitemap = SitemapApp(
96 self,
97 domain=self.config.domain,
98 cache_ttl=self.config.cache_ttl,
99 )
100 debug(f"NativeSitemap: Initialized with domain={self.config.domain}")
103Sitemap = NativeSitemap
105MODULE_ID = UUID("01937d86-9f7f-7081-d342-6789012345f0")
106MODULE_STATUS = AdapterStatus.STABLE
108with suppress(Exception):
109 depends.set(Sitemap)