Coverage for fastblocks/adapters/sitemap/native.py: 0%
71 statements
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-09 00:47 -0700
« prev ^ index » next coverage.py v7.10.7, created at 2025-10-09 00:47 -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
8import typing as t
9from contextlib import suppress
10from uuid import UUID
12from acb.adapters import AdapterStatus
13from acb.debug import debug
14from acb.depends import depends
16from ._base import SitemapBase, SitemapBaseSettings
17from .core import BaseSitemap, SitemapApp
20class NativeSitemapSettings(SitemapBaseSettings):
21 pass
24class NativeSitemap(BaseSitemap[str], SitemapBase): # type: ignore[override]
25 sitemap: SitemapApp | None = None
27 def items(self) -> t.Any:
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.copy()
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 t.cast(str, 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 if segments == 2:
87 return 0.6
88 return 0.4
90 async def init(self) -> None:
91 if not self.config.domain:
92 msg = "domain must be set in sitemap settings"
93 raise ValueError(msg)
94 self.sitemap = SitemapApp(
95 self,
96 domain=self.config.domain,
97 cache_ttl=self.config.cache_ttl,
98 )
99 debug(f"NativeSitemap: Initialized with domain={self.config.domain}")
102Sitemap = NativeSitemap
104MODULE_ID = UUID("01937d86-9f7f-7081-d342-6789012345f0")
105MODULE_STATUS = AdapterStatus.STABLE
107with suppress(Exception):
108 depends.set(Sitemap)