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