1#!/usr/bin/env python3
2"""
3
4"""
5# Imports:
6from __future__ import annotations
7
8# ##-- stdlib imports
9import datetime
10import enum
11import functools as ftz
12import itertools as itz
13import logging as logmod
14import pathlib as pl
15import re
16import time
17import types
18import collections
19import contextlib
20import hashlib
21from copy import deepcopy
22from uuid import UUID, uuid1
23from weakref import ref
24import atexit # for @atexit.register
25import faulthandler
26# ##-- end stdlib imports
27
28import bibble._interface as API
29
30# ##-- types
31# isort: off
32import abc
33import collections.abc
34from typing import TYPE_CHECKING, cast, assert_type, assert_never
35from typing import Generic, NewType
36# Protocols:
37from typing import Protocol, runtime_checkable
38# Typing Decorators:
39from typing import no_type_check, final, override, overload
40
41if TYPE_CHECKING:
42 from jgdv import Maybe, Fifo, Lifo
43 from typing import Final
44 from typing import ClassVar, Any, LiteralString
45 from typing import Never, Self, Literal
46 from typing import TypeGuard
47 from collections.abc import Iterable, Iterator, Callable, Generator
48 from collections.abc import Sequence, Mapping, MutableMapping, Hashable
49
50 type UniMiddleware = API.UniMiddleware
51 type BidiMiddleware = API.BidiMiddleware
52 type Middleware = API.Middleware
53
54##--|
55
56# isort: on
57# ##-- end types
58
59##-- logging
60logging = logmod.getLogger(__name__)
61##-- end logging
62
63# Vars:
64
65# Body:
66
[docs]
67class PairStack:
68 """ A pair of middleware stacks,
69 allowing reader/writer pairs to be added at the same time
70
71 The read stack is Fifo, the write stack is Lifo.
72 So any transforms are undone in the correct order before writing.
73 Parse[m1, m2, m3] -> Write[m3, m2, m1]
74
75 eg: Parse[LatexToUnicode, SplitName] -> Write[MergeNames, UnicodeToLatex]
76
77 """
78 _read_time : Fifo[Middleware]
79 _write_time : Lifo[Middleware]
80
81 def __init__(self):
82 self._read_time = []
83 self._write_time = []
84
[docs]
85 def add(self, *bidis:BidiMiddleware, read:Maybe[list[Middleware]]=None, write:Maybe[list[Middleware]]=None) -> Self:
86 """
87 Add middlewares to the read/write stacks.
88 Args *must* be bidirection, and will be added to both.
89 kwargs 'read' and 'write' just add to specific stacks
90 """
91 read = read or []
92 write = write or []
93
94 for mid in bidis:
95 match mid:
96 case None:
97 pass
98 case API.BidirectionalMiddleware_p():
99 self._read_time.append(mid)
100 self._write_time.append(mid)
101 case x:
102 raise TypeError(type(x))
103
104 for x in read:
105 match x:
106 case None:
107 pass
108 case API.Middleware_p():
109 self._read_time.append(x)
110 case API.BidirectionalMiddleware_p():
111 self._read_time.append(x)
112 case _:
113 raise TypeError(type(x))
114
115 for x in write:
116 match x:
117 case None:
118 pass
119 case API.Middleware_p():
120 self._write_time.append(x)
121 case API.BidirectionalMiddleware_p():
122 self._write_time.append(x)
123 case _:
124 raise TypeError(type(x))
125
126 return self
127
[docs]
128 def read_stack(self) -> list[Middleware]:
129 """ Return the read stack """
130 return self._read_time[:]
131
[docs]
132 def write_stack(self) -> list[Middleware]:
133 """ Return the write stack """
134 return self._write_time[::-1]
135
144
153
154 def __contains__(self, other:type[Middleware]|Middleware) -> bool:
155 return self.has_read_transform(other) or self.has_write_transform(other)