modm_data.html.chapter

 1# Copyright 2022, Niklas Hauser
 2# SPDX-License-Identifier: MPL-2.0
 3
 4import re
 5import logging
 6from pathlib import Path
 7from functools import cached_property
 8from .parser import Parser
 9from .table import Table
10from .text import Heading, Text
11
12LOGGER = logging.getLogger(__name__)
13
14
15class Chapter:
16    def __init__(self, path: str):
17        self._path = Path(path)
18
19    @cached_property
20    def _parser(self):
21        parser = Parser()
22        parser.feed(self._path.read_text())
23        return parser
24
25    @property
26    def _relpath(self) -> str:
27        return self._path.relative_to(Path().cwd())
28
29    @property
30    def name(self) -> str:
31        return self._path.stem.replace("_", " ")
32
33    @property
34    def number(self) -> int:
35        return int(self._path.stem.split("_")[1])
36
37    @property
38    def items(self) -> list:
39        return self._parser._items
40
41    def headings(self) -> list[str]:
42        return [h for h in self.items if isinstance(h, Heading)]
43
44    def texts(self) -> list[str]:
45        return [t for t in self.items if isinstance(t, Text)]
46
47    def _heading_objects(self, obj_type, pattern, **subs) -> list:
48        heading_texts = []
49        current = [None, []]
50        for item in self.items:
51            if isinstance(item, Heading):
52                if current[1]:
53                    heading_texts.append(tuple(current))
54                current = [item, []]
55            elif isinstance(item, obj_type):
56                current[1].append(item)
57        if current[1]:
58            heading_texts.append(tuple(current))
59        if pattern is None: return heading_texts
60        return [ht for ht in heading_texts if re.search(pattern,
61                ht[0].text(**subs) if ht[0] is not None else "", re.IGNORECASE)]
62
63    def heading_texts(self, pattern=None, **subs) -> list:
64        return self._heading_objects(Text, pattern, **subs)
65
66    def heading_tables(self, pattern=None, **subs) -> list:
67        return self._heading_objects(Table, pattern, **subs)
68
69    def tables(self, pattern: str = None, **subs) -> list[Table]:
70        tables = [t for t in self.items if isinstance(t, Table)]
71        if pattern is None: return tables
72        return [t for t in tables if re.search(pattern, t.caption(**subs), re.IGNORECASE)]
73
74    def table(self, pattern: str) -> Table:
75        tables = self.tables(pattern)
76        if len(tables) == 0:
77            LOGGER.error(f"Cannot find table with pattern '{pattern}'!")
78        if len(tables) > 1:
79            LOGGER.error(f"Found multiple tables with pattern '{pattern}'!")
80        assert len(tables) == 1
81        return tables[0]
82
83    def __hash__(self) -> int:
84        return hash(self._path.stem)
85
86    def __eq__(self) -> int:
87        return hash(self._path.stem)
88
89    def __repr__(self) -> str:
90        return f"Chapter({self.name})"
LOGGER = <Logger modm_data.html.chapter (WARNING)>
class Chapter:
16class Chapter:
17    def __init__(self, path: str):
18        self._path = Path(path)
19
20    @cached_property
21    def _parser(self):
22        parser = Parser()
23        parser.feed(self._path.read_text())
24        return parser
25
26    @property
27    def _relpath(self) -> str:
28        return self._path.relative_to(Path().cwd())
29
30    @property
31    def name(self) -> str:
32        return self._path.stem.replace("_", " ")
33
34    @property
35    def number(self) -> int:
36        return int(self._path.stem.split("_")[1])
37
38    @property
39    def items(self) -> list:
40        return self._parser._items
41
42    def headings(self) -> list[str]:
43        return [h for h in self.items if isinstance(h, Heading)]
44
45    def texts(self) -> list[str]:
46        return [t for t in self.items if isinstance(t, Text)]
47
48    def _heading_objects(self, obj_type, pattern, **subs) -> list:
49        heading_texts = []
50        current = [None, []]
51        for item in self.items:
52            if isinstance(item, Heading):
53                if current[1]:
54                    heading_texts.append(tuple(current))
55                current = [item, []]
56            elif isinstance(item, obj_type):
57                current[1].append(item)
58        if current[1]:
59            heading_texts.append(tuple(current))
60        if pattern is None: return heading_texts
61        return [ht for ht in heading_texts if re.search(pattern,
62                ht[0].text(**subs) if ht[0] is not None else "", re.IGNORECASE)]
63
64    def heading_texts(self, pattern=None, **subs) -> list:
65        return self._heading_objects(Text, pattern, **subs)
66
67    def heading_tables(self, pattern=None, **subs) -> list:
68        return self._heading_objects(Table, pattern, **subs)
69
70    def tables(self, pattern: str = None, **subs) -> list[Table]:
71        tables = [t for t in self.items if isinstance(t, Table)]
72        if pattern is None: return tables
73        return [t for t in tables if re.search(pattern, t.caption(**subs), re.IGNORECASE)]
74
75    def table(self, pattern: str) -> Table:
76        tables = self.tables(pattern)
77        if len(tables) == 0:
78            LOGGER.error(f"Cannot find table with pattern '{pattern}'!")
79        if len(tables) > 1:
80            LOGGER.error(f"Found multiple tables with pattern '{pattern}'!")
81        assert len(tables) == 1
82        return tables[0]
83
84    def __hash__(self) -> int:
85        return hash(self._path.stem)
86
87    def __eq__(self) -> int:
88        return hash(self._path.stem)
89
90    def __repr__(self) -> str:
91        return f"Chapter({self.name})"
Chapter(path: str)
17    def __init__(self, path: str):
18        self._path = Path(path)
name: str
30    @property
31    def name(self) -> str:
32        return self._path.stem.replace("_", " ")
number: int
34    @property
35    def number(self) -> int:
36        return int(self._path.stem.split("_")[1])
items: list
38    @property
39    def items(self) -> list:
40        return self._parser._items
def headings(self) -> list[str]:
42    def headings(self) -> list[str]:
43        return [h for h in self.items if isinstance(h, Heading)]
def texts(self) -> list[str]:
45    def texts(self) -> list[str]:
46        return [t for t in self.items if isinstance(t, Text)]
def heading_texts(self, pattern=None, **subs) -> list:
64    def heading_texts(self, pattern=None, **subs) -> list:
65        return self._heading_objects(Text, pattern, **subs)
def heading_tables(self, pattern=None, **subs) -> list:
67    def heading_tables(self, pattern=None, **subs) -> list:
68        return self._heading_objects(Table, pattern, **subs)
def tables(self, pattern: str = None, **subs) -> list[modm_data.html.table.Table]:
70    def tables(self, pattern: str = None, **subs) -> list[Table]:
71        tables = [t for t in self.items if isinstance(t, Table)]
72        if pattern is None: return tables
73        return [t for t in tables if re.search(pattern, t.caption(**subs), re.IGNORECASE)]
def table(self, pattern: str) -> modm_data.html.table.Table:
75    def table(self, pattern: str) -> Table:
76        tables = self.tables(pattern)
77        if len(tables) == 0:
78            LOGGER.error(f"Cannot find table with pattern '{pattern}'!")
79        if len(tables) > 1:
80            LOGGER.error(f"Found multiple tables with pattern '{pattern}'!")
81        assert len(tables) == 1
82        return tables[0]