Path:
strictdoc/backend/sdoc/grammar_reader.py
Lines:
81
Non-empty lines:
68
Non-empty lines covered with requirements:
68 / 68 (100.0%)
Functions:
3
Functions covered by requirements:
3 / 3 (100.0%)
1
from typing import Optional
2
3
from textx import metamodel_from_str
4
5
from strictdoc.backend.sdoc.grammar.grammar_builder import SDocGrammarBuilder
6
from strictdoc.backend.sdoc.models.constants import GRAMMAR_MODELS
7
from strictdoc.backend.sdoc.models.document_grammar import (
8
DocumentGrammar,
9
DocumentGrammarWrapper,
10
)11
from strictdoc.backend.sdoc.pickle_cache import PickleCache
12
from strictdoc.core.project_config import ProjectConfig
13
from strictdoc.helpers.cast import assert_optional_cast
14
from strictdoc.helpers.exception import StrictDocException
15
from strictdoc.helpers.file_system import file_open_read_utf8
16
from strictdoc.helpers.textx import (
17
drop_textx_meta,
18
preserve_source_location_data,
19
)20
21
22
class SDocGrammarReader:
23
meta_model = metamodel_from_str(
24
SDocGrammarBuilder.create_grammar_grammar(),
25
classes=GRAMMAR_MODELS + [DocumentGrammarWrapper],
26
use_regexp_group=True,
27
)28
29
@staticmethod30
def read(
31
input_string: str, file_path: Optional[str] = None
32
) -> DocumentGrammar:
33
SDocGrammarReader.meta_model.register_obj_processors(
34
{35
"GrammarElement": preserve_source_location_data,
36
}37
)38
39
try:
40
grammar_wrapper: DocumentGrammarWrapper = (
41
SDocGrammarReader.meta_model.model_from_str(
42
input_string, file_name=file_path
43
)44
)45
except Exception as exc_: # pylint: disable=broad-except
46
raise StrictDocException(
47
f"Could not parse file: "
48
f"{file_path}. "
49
f"Error: {exc_.__class__.__name__}: {exc_}"
50
) from exc_
51
52
grammar: DocumentGrammar = grammar_wrapper.grammar
53
grammar.parent = None
54
55
# HACK:56
# ProcessPoolExecutor doesn't work because of non-picklable parts57
# of textx. The offending fields are stripped down because they58
# are not used anyway.59
drop_textx_meta(grammar)
60
61
return grammar
62
63
def read_from_file(
64
self, file_path: str, project_config: ProjectConfig
65
) -> DocumentGrammar:
66
unpickled_content: Optional[DocumentGrammar] = assert_optional_cast(
67
PickleCache.read_from_cache(file_path, project_config, "grammar"),
68
DocumentGrammar,
69
)70
if unpickled_content is not None:
71
return unpickled_content
72
73
with file_open_read_utf8(file_path) as file:
74
grammar_content = file.read()
75
76
grammar: DocumentGrammar = self.read(
77
grammar_content, file_path=file_path
78
)79
PickleCache.save_to_cache(grammar, file_path, project_config, "grammar")
80
81
return grammar