1
|
1 |
|
import log |
2
|
|
|
|
3
|
1 |
|
from ._base import Service |
4
|
1 |
|
from ..domain import Template, Placeholder |
5
|
|
|
|
6
|
|
|
|
7
|
1 |
|
class TemplateService(Service): |
8
|
|
|
|
9
|
|
|
def __init__(self, template_store, **kwargs): |
10
|
1 |
|
super().__init__(**kwargs) |
11
|
|
|
self.template_store = template_store |
12
|
1 |
|
|
13
|
1 |
|
def all(self): |
14
|
1 |
|
"""Get all templates.""" |
15
|
|
|
templates = self.template_store.filter() |
16
|
1 |
|
return templates |
17
|
|
|
|
18
|
1 |
|
def find(self, key, *, allow_missing=False): |
19
|
1 |
|
"""Find a template with a matching key.""" |
20
|
|
|
|
21
|
1 |
|
# Find an exact match |
22
|
|
|
key2 = Template.strip(key, keep_special=True) |
23
|
|
|
template = self.template_store.read(key2) |
24
|
|
|
if template: |
25
|
1 |
|
return template |
26
|
1 |
|
|
27
|
1 |
|
# Else, find an alias match |
28
|
1 |
|
key2 = Template.strip(key2) |
29
|
|
|
for template in self.all(): |
30
|
|
|
if key2 in template.aliases_stripped: |
31
|
1 |
|
return template |
32
|
1 |
|
|
33
|
1 |
|
# Else, no match |
34
|
1 |
|
if allow_missing: |
35
|
|
|
return Placeholder(key) |
36
|
|
|
|
37
|
1 |
|
raise self.exceptions.TemplateNotFound |
38
|
1 |
|
|
39
|
|
|
def aliases(self, query=None): |
40
|
1 |
|
"""Get all aliases with an optional name filter.""" |
41
|
|
|
names = [] |
42
|
1 |
|
for template in self.all(): |
43
|
|
|
for name in [template.key] + template.aliases: |
44
|
1 |
|
if query is None or query in name: |
45
|
1 |
|
names.append(name) |
46
|
1 |
|
return names |
47
|
1 |
|
|
48
|
1 |
|
def validate(self): |
49
|
1 |
|
"""Ensure all templates are valid and conflict-free.""" |
50
|
|
|
templates = self.all() |
51
|
1 |
|
keys = {template.key: template for template in templates} |
52
|
|
|
for template in templates: |
53
|
1 |
|
log.info(f"Checking template '{template}'") |
54
|
1 |
|
if not template.validate(): |
55
|
1 |
|
return False |
56
|
1 |
|
for alias in template.aliases: |
57
|
1 |
|
log.info(f"Checking alias '{alias}' -> '{template.key}'") |
58
|
1 |
|
if alias not in template.aliases_lowercase: |
59
|
1 |
|
msg = "Alias '%s' should be lowercase characters or dashes" |
60
|
1 |
|
log.error(msg, alias) |
61
|
1 |
|
return False |
62
|
1 |
|
try: |
63
|
1 |
|
existing = keys[alias] |
64
|
1 |
|
except KeyError: |
65
|
1 |
|
keys[alias] = template |
66
|
1 |
|
else: |
67
|
1 |
|
msg = "Alias '%s' already used in template: %s" |
68
|
1 |
|
log.error(msg, alias, existing) |
69
|
|
|
return False |
70
|
|
|
return True |
71
|
|
|
|