Skip to content
This repository was archived by the owner on Jun 27, 2023. It is now read-only.

Commit e6981bd

Browse files
Sentinel implementation
1 parent dd90b05 commit e6981bd

4 files changed

Lines changed: 42 additions & 42 deletions

File tree

multibar/impl.py

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@
1111
from multibar.interfaces.containers import AbstractSeqBasedContainerMixin
1212
from multibar.interfaces.customer import AbstractCustomerMixin
1313
from multibar.interfaces.product import AbstractSectorMixin
14-
from multibar.internal.crate import (
15-
ProgressbarContainer,
16-
ProgressContainer,
17-
SectorContainer,
18-
)
14+
from multibar.internal.crate import ProgressbarContainer
15+
from multibar.internal.crate import ProgressContainer
16+
from multibar.internal.crate import SectorContainer
1917
from multibar.internal.factories import SphinxSectorFactory
2018
from multibar.internal.product import Sector
2119
from multibar.pytypes import NoneType, NotImplementedType
20+
from multibar.internal.sentinel import MissingOr, MISSING, Sentinel
2221

2322
_AbcSectorT_co = TypeVar("_AbcSectorT_co", bound=AbstractSectorMixin, covariant=True)
2423
_AbcContainerT_co = TypeVar("_AbcContainerT_co", bound=AbstractSeqBasedContainerMixin[Any], covariant=True)
@@ -54,15 +53,15 @@ class ProgressBar(Generic[_AbcSectorT_co, _AbcContainerT_co]):
5453
length: :class:`int` = 20
5554
Length of progress bar.
5655
57-
sector_cls: :class:`Optional[Type[AbstractSectorMixin]]` = None
56+
sector_cls: :class:`MissingOr[Type[AbstractSectorMixin]]` = MISSING
5857
Custom Sector implementation.
5958
6059
For more information and examples see:
6160
https://animatea.github.io/python-multibar/abc/?h=abstractsectormixin
6261
63-
container_cls: :class:`Optional[
62+
container_cls: :class:`MissingOr[
6463
Type[AbstractSeqBasedContainerMixin[AbstractSectorMixin]]
65-
] = None`
64+
] = MISSING`
6665
Custom container implementation.
6766
6867
For more information and examples see:
@@ -72,19 +71,19 @@ class ProgressBar(Generic[_AbcSectorT_co, _AbcContainerT_co]):
7271
current: int
7372
total: int
7473
length: int = 20
75-
sector_cls: Optional[Type[_AbcSectorT_co]] = None
76-
container_cls: Optional[Type[_AbcContainerT_co]] = None
74+
sector_cls: MissingOr[Type[_AbcSectorT_co]] = MISSING
75+
container_cls: MissingOr[Type[_AbcContainerT_co]] = MISSING
7776

7877
def __post_init__(self) -> None:
7978
assert self.current >= 0, "Current progress cannot be less than 0."
8079
assert self.current <= self.total, "Current progress cannot be more than total progress."
8180

82-
if self.container_cls is None:
81+
if self.container_cls is MISSING:
8382
self.container_cls = SectorContainer # type: ignore[assignment]
8483

8584
self.factory: SphinxSectorFactory[AbstractSectorMixin] = SphinxSectorFactory.from_bind(
8685
sector_type=cast(
87-
Type[AbstractSectorMixin], Sector if self.sector_cls is None else self.sector_cls
86+
Type[AbstractSectorMixin], Sector if self.sector_cls is MISSING else self.sector_cls
8887
)
8988
)
9089

@@ -93,10 +92,10 @@ def write_progress(
9392
*args: Any,
9493
fill: str,
9594
line: str,
96-
start: Optional[str] = None,
97-
unfilled_start: Optional[str] = None,
98-
end: Optional[str] = None,
99-
unfilled_end: Optional[str] = None,
95+
start: MissingOr[str] = MISSING,
96+
unfilled_start: MissingOr[str] = MISSING,
97+
end: MissingOr[str] = MISSING,
98+
unfilled_end: MissingOr[str] = MISSING,
10099
**kwargs: Any,
101100
) -> ProgressbarContainer[_AbcSectorT_co]:
102101
# TODO: Maybe adapter?
@@ -122,16 +121,16 @@ def write_progress(
122121
!!! Abstract:
123122
This symbol is used on last (second) fill (depending on progress).
124123
125-
start: :class:`Optional[str]` = None
124+
start: :class:`MissingOr[str]` = MISSING
126125
If passed, will replace first FILLED emoji of progress bar (depending on progress).
127126
128-
unfilled_start: :class:`Optional[str]` = None
127+
unfilled_start: :class:`MissingOr[str]` = MISSING
129128
If passed, will replace first EMPTY emoji of progress bar (depending on progress).
130129
131-
end: :class:`Optional[str]` = None
130+
end: :class:`MissingOr[str]` = MISSING
132131
If passed, will replace last FILLED emoji of progress bar (depending on progress).
133132
134-
unfilled_end: :class:`Optional[str]` = None
133+
unfilled_end: :class:`MissingOr[str]` = MISSING
135134
If passed, will replace last EMPTY emoji of progress bar (depending on progress).
136135
137136
**kwargs: :class:`Any`
@@ -142,7 +141,7 @@ def write_progress(
142141
"""
143142
progress = ProgressContainer(self.current, self.total)
144143
percents = progress.percents(allow_float=False)
145-
assert self.container_cls is not None
144+
assert self.container_cls is not MISSING
146145

147146
with self.container_cls() as container:
148147
for i in range(rest := (round(percents / (100 / self.length)))):
@@ -168,21 +167,21 @@ def write_progress(
168167
)
169168

170169
# Add `unfilled_start` if it is specified and none of the sectors is yet filled.
171-
if unfilled_start is not None and percents < FillFlag.FIRST:
170+
if unfilled_start is not MISSING and percents < FillFlag.FIRST:
172171
container[0].name = unfilled_start
173172

174173
# Otherwise, if `start` is specified, it will be added to the beginning.
175-
elif percents >= FillFlag.FIRST and start is not None:
174+
elif percents >= FillFlag.FIRST and start is not MISSING:
176175
container[0].name = start
177176

178177
# If `unfilled_end` is specified and the last sector is not filled, then the
179178
# corresponding character will be added to the end of the progress bar.
180-
if unfilled_end is not None and percents < FillFlag.LAST:
179+
if unfilled_end is not MISSING and percents < FillFlag.LAST:
181180
container[-1].name = unfilled_end
182181

183182
# Otherwise, if end is specified, the character corresponding to the
184183
# given argument will be appended to the end of the progressbar.
185-
elif percents >= FillFlag.LAST and end is not None:
184+
elif percents >= FillFlag.LAST and end is not MISSING:
186185
container[-1].name = end
187186

188187
return ProgressbarContainer(
@@ -196,11 +195,11 @@ async def async_write_progress(
196195
*args: Any,
197196
fill: str,
198197
line: str,
199-
start: Optional[str] = None,
200-
unfilled_start: Optional[str] = None,
201-
end: Optional[str] = None,
202-
unfilled_end: Optional[str] = None,
203-
loop: Optional[asyncio.AbstractEventLoop] = None,
198+
start: Optional[str] = MISSING,
199+
unfilled_start: Optional[str] = MISSING,
200+
end: Optional[str] = MISSING,
201+
unfilled_end: Optional[str] = MISSING,
202+
loop: Optional[asyncio.AbstractEventLoop] = MISSING,
204203
**kwargs: Any,
205204
) -> Coroutine[ProgressbarContainer[_AbcSectorT_co], None, None]:
206205
"""``sync method``
@@ -224,19 +223,19 @@ async def async_write_progress(
224223
!!! Abstract:
225224
This symbol is used on last (second) fill (depending on progress).
226225
227-
start: :class:`Optional[str]` = None
226+
start: :class:`MissingOr[str]` = MISSING
228227
If passed, will replace first FILLED emoji of progress bar (depending on progress).
229228
230-
unfilled_start: :class:`Optional[str]` = None
229+
unfilled_start: :class:`MissingOr[str]` = MISSING
231230
If passed, will replace first EMPTY emoji of progress bar (depending on progress).
232231
233-
end: :class:`Optional[str]` = None
232+
end: :class:`MissingOr[str]` = MISSING
234233
If passed, will replace last FILLED emoji of progress bar (depending on progress).
235234
236-
unfilled_end: :class:`Optional[str]` = None
235+
unfilled_end: :class:`MissingOr[str]` = MISSING
237236
If passed, will replace last EMPTY emoji of progress bar (depending on progress).
238237
239-
loop: :class:`Optional[asyncio.AbstractEventLoop]` = None
238+
loop: :class:`MissingOr[asyncio.AbstractEventLoop]` = MISSING
240239
Event loop that used for creating awaitable object and further run in executor.
241240
242241
**kwargs: :class:`Any`
@@ -245,7 +244,7 @@ async def async_write_progress(
245244
For more information and examples see:
246245
https://animatea.github.io/python-multibar/abc/?h=abstractseqbasedcontainermixin
247246
"""
248-
if loop is None:
247+
if loop is MISSING:
249248
loop = asyncio.get_event_loop()
250249

251250
return cast(
@@ -296,7 +295,7 @@ def write_from_customer(
296295
kwargs_new = {}
297296
for as_str in AbstractCustomerMixin.__abstractmethods__:
298297
progress_char = getattr(customer, as_str)(customer, ctx)
299-
if not isinstance(progress_char, (NotImplementedType, NoneType)):
298+
if not isinstance(progress_char, (Sentinel, NotImplementedType, NoneType)):
300299
kwargs_new[as_str] = progress_char
301300

302301
kwargs.update(kwargs_new)
@@ -306,7 +305,7 @@ async def async_write_from_customer(
306305
self,
307306
*args: Any,
308307
customer: Type[AbstractCustomerMixin],
309-
loop: Optional[asyncio.AbstractEventLoop] = None,
308+
loop: MissingOr[asyncio.AbstractEventLoop] = MISSING,
310309
**kwargs: Any,
311310
) -> Coroutine[ProgressbarContainer[_AbcSectorT_co], None, None]:
312311
"""``sync method``
@@ -323,7 +322,7 @@ async def async_write_from_customer(
323322
customer: :class:`Type[AbstractCustomerMixin]`
324323
Customer implementation class.
325324
326-
loop: :class:`Optional[asyncio.AbstractEventLoop]` = None
325+
loop: :class:`MissingOr[asyncio.AbstractEventLoop]` = MISSING
327326
Event loop that used for creating awaitable object and further run in executor.
328327
329328
**kwargs: :class:`Any`
@@ -332,7 +331,7 @@ async def async_write_from_customer(
332331
For more information and examples see:
333332
https://animatea.github.io/python-multibar/abc/?h=abstractseqbasedcontainermixin
334333
"""
335-
if loop is None:
334+
if loop is MISSING:
336335
loop = asyncio.get_event_loop()
337336

338337
return cast(

multibar/internal/py.typed

Whitespace-only changes.

multibar/internal/sentinel.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from __future__ import annotations
22

3-
__all__ = ["Sentinel", "MISSING", "MissingOr"]
3+
__all__ = ["Sentinel", "MISSING", "MissingOr", "MissingNoneOr"]
44

55
from typing import (
66
TYPE_CHECKING,
@@ -62,3 +62,4 @@ def new(cls, name: str, *, repr: Optional[str] = None) -> _SentinelProto:
6262

6363
T = TypeVar("T")
6464
MissingOr = Union[T, Sentinel]
65+
MissingNoneOr = Union[MissingOr[T], None]

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def long_description() -> str:
1111

1212
setuptools.setup(
1313
name="python-multibar",
14-
version="3.0.1",
14+
version="3.0.2",
1515
keywords=[
1616
"PYTHON",
1717
"PYTHON3",

0 commit comments

Comments
 (0)