Passed
Push — main ( 3a643b...e33dea )
by Sat CFDI
01:53
created

finalize_html()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nop 1
1
import logging
2
from decimal import Decimal
3
from html import escape as html_escape
4
import collections.abc
5
import jinja2
6
import yaml
7
from jinja2 import Environment
8
from jinja2.filters import do_mark_safe
9
from satcfdi import Code
10
from satcfdi.pacs import sat
11
# noinspection PyUnresolvedReferences
12
from satcfdi.transform.catalog import CATALOGS
13
from satcfdi.transform.helpers import Xint
14
from yaml import MappingNode
15
from yaml.constructor import ConstructorError
16
17
REGIMEN_FISCAL = CATALOGS['{http://www.sat.gob.mx/sitio_internet/cfd/catalogos}c_RegimenFiscal']
18
19
logger = logging.getLogger(__name__)
20
sat_manager = sat.SAT()
21
22
environment_default = Environment(
23
    loader=jinja2.FileSystemLoader(searchpath=['templates']),
24
    autoescape=False,
25
    trim_blocks=True,
26
    lstrip_blocks=True,
27
    undefined=jinja2.StrictUndefined,
28
)
29
30
31
def finalize_html(val):
32
    return do_mark_safe(
33
        tag(html_escape(val), "b")
34
    )
35
36
37
environment_bold_escaped = Environment(
38
    loader=jinja2.FileSystemLoader(searchpath=['templates']),
39
    autoescape=True,
40
    trim_blocks=True,
41
    lstrip_blocks=True,
42
    undefined=jinja2.StrictUndefined,
43
    finalize=finalize_html
44
)
45
46
47
class DuplicateKeySafeLoader(yaml.SafeLoader):
48
    def construct_mapping(self, node, deep=False):
49
        if isinstance(node, MappingNode):
50
            self.flatten_mapping(node)
51
52
        if not isinstance(node, MappingNode):
53
            raise ConstructorError(None, None,
54
                                   "expected a mapping node, but found %s" % node.id,
55
                                   node.start_mark)
56
        mapping = {}
57
        for key_node, value_node in node.value:
58
            key = self.construct_object(key_node, deep=deep)
59
            if not isinstance(key, collections.abc.Hashable):
60
                raise ConstructorError("while constructing a mapping", node.start_mark,
61
                                       "found unhashable key", key_node.start_mark)
62
            value = self.construct_object(value_node, deep=deep)
63
            if key in mapping:
64
                raise ConstructorError("while constructing a mapping", node.start_mark,
65
                                       "found duplicate key (%s)" % key, key_node.start_mark)
66
            mapping[key] = value
67
        return mapping
68
69
70
class LocalData(dict):
71
    file_source = None
72
73
    def __new__(cls, *args, **kwargs):
74
        return super().__new__(cls)
75
76
    def __init__(self):
77
        super().__init__(self._raw())
78
79
    def reload(self):
80
        super().update(self._raw())
81
82
    def _raw(self):
83
        with open(self.file_source, "r", encoding="utf-8") as fs:
84
            return yaml.load(fs, DuplicateKeySafeLoader)
85
86
87
class ConfigManager(LocalData):
88
    file_source = "config.yaml"
89
90
    def folio(self):
91
        return self["folio"]
92
93
    def serie(self):
94
        return self["serie"]
95
96
    def inc_folio(self):
97
        self["folio"] += 1
98
        self.save()
99
100
    def save(self):
101
        with open(self.file_source, "w", encoding="utf-8") as fs:
102
            yaml.dump_all([self], fs, Dumper=yaml.SafeDumper, encoding="utf-8", allow_unicode=True, sort_keys=False)
103
104
105
class ClientsManager(LocalData):
106
    file_source = "clients.yaml"
107
108
    def __init__(self):
109
        super().__init__()
110
        for k in self:
111
            self[k]["Rfc"] = k
112
            self[k]["RegimenFiscal"] = Code(self[k]["RegimenFiscal"], REGIMEN_FISCAL.get(self[k]["RegimenFiscal"]))
113
114
115
class FacturasManager(LocalData):
116
    file_source = "facturas.yaml"
117
118
119
def tag(text, tag):
120
    return '<' + tag + '>' + text + '</' + tag + '>'
121
122
123
yaml.SafeDumper.add_multi_representer(dict, lambda dumper, data: dumper.represent_dict(data))
124
yaml.SafeLoader.add_constructor("!decimal", lambda loader, node: Decimal(loader.construct_scalar(node)))
125
126
127
def represent_decimal(dumper, data):
128
    return dumper.represent_scalar('tag:yaml.org,2002:str', str(data))
129
130
131
def represent_str(dumper, data):
132
    return dumper.represent_scalar('tag:yaml.org,2002:str', str(data))
133
134
135
yaml.SafeDumper.add_representer(Decimal, represent_decimal)
136
yaml.SafeDumper.add_representer(Code, represent_str)
137
yaml.SafeDumper.add_representer(Xint, represent_str)
138