chromatic-python 0.3.0__tar.gz → 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. {chromatic_python-0.3.0/chromatic_python.egg-info → chromatic_python-0.3.1}/PKG-INFO +1 -1
  2. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/_typing.py +37 -14
  3. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/_version.py +2 -2
  4. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/color/colorconv.py +26 -6
  5. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/color/core.py +95 -33
  6. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/color/core.pyi +63 -15
  7. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/color/iterators.py +11 -5
  8. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/color/palette.py +36 -12
  9. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/color/palette.pyi +19 -3
  10. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/__init__.py +8 -1
  11. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/__init__.pyi +8 -1
  12. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/userfont.py +9 -3
  13. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/userfont.pyi +3 -1
  14. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/demo.py +43 -17
  15. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/image/_array.py +379 -368
  16. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/image/_glyph_proc.py +2 -10
  17. {chromatic_python-0.3.0 → chromatic_python-0.3.1/chromatic_python.egg-info}/PKG-INFO +1 -1
  18. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/tests/test_color_str.py +17 -5
  19. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/.gitattributes +0 -0
  20. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/.gitignore +0 -0
  21. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/LICENSE +0 -0
  22. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/README.md +0 -0
  23. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/__init__.py +0 -0
  24. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/__init__.pyi +0 -0
  25. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/color/__init__.py +0 -0
  26. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/color/__init__.pyi +0 -0
  27. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/_fetchers.py +0 -0
  28. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/butterfly.jpg +0 -0
  29. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/escher.png +0 -0
  30. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/fonts/consolas.ttf +0 -0
  31. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/fonts/vga437.ttf +0 -0
  32. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/goblin_virus.png +0 -0
  33. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/registry.json +0 -0
  34. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/data/userfont.schema.json +0 -0
  35. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/image/__init__.py +0 -0
  36. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/image/__init__.pyi +0 -0
  37. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic/image/_curses.py +0 -0
  38. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic_python.egg-info/SOURCES.txt +0 -0
  39. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic_python.egg-info/dependency_links.txt +0 -0
  40. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic_python.egg-info/requires.txt +0 -0
  41. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/chromatic_python.egg-info/top_level.txt +0 -0
  42. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/logo/logo.ANS +0 -0
  43. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/logo/logo.PNG +0 -0
  44. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/pyproject.toml +0 -0
  45. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/requirements.txt +0 -0
  46. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/setup.cfg +0 -0
  47. {chromatic_python-0.3.0 → chromatic_python-0.3.1}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chromatic-python
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: ANSI art image processing and colored terminal text
5
5
  Author: crypt0lith
6
6
  License: MIT License
@@ -50,8 +50,12 @@ _T_co = TypeVar('_T_co', covariant=True)
50
50
  _T_contra = TypeVar('_T_contra', contravariant=True)
51
51
  _AnyNumber_co = TypeVar('_AnyNumber_co', number, Number, covariant=True)
52
52
 
53
- type ArrayReducerFunc[_SCT: generic] = Callable[Concatenate[_ArrayLike[_SCT], _P], NDArray[_SCT]]
54
- type ShapedNDArray[_Shape: tuple[int, ...], _SCT = generic] = ndarray[_Shape, dtype[_SCT]]
53
+ type ArrayReducerFunc[_SCT: generic] = Callable[
54
+ Concatenate[_ArrayLike[_SCT], _P], NDArray[_SCT]
55
+ ]
56
+ type ShapedNDArray[_Shape: tuple[int, ...], _SCT = generic] = ndarray[
57
+ _Shape, dtype[_SCT]
58
+ ]
55
59
  type MatrixLike[_SCT: generic] = ShapedNDArray[TupleOf2[int], _SCT]
56
60
  type SquareMatrix[_I: int, _SCT: generic] = ShapedNDArray[TupleOf2[_I], _SCT]
57
61
  type GlyphArray[_SCT: generic] = SquareMatrix[L[24], _SCT]
@@ -100,7 +104,11 @@ def type_error_msg(err_obj, *expected, context: str = '', obj_repr=False):
100
104
  name_slots = ["{%d.__name__!r}" % n for n in range(n_expected)]
101
105
  if n_expected > 1:
102
106
  name_slots[-1] = f"or {name_slots[-1]}"
103
- names = (', ' if n_expected > 2 else ' ').join([context.strip(), *name_slots]).format(*expected)
107
+ names = (
108
+ (', ' if n_expected > 2 else ' ')
109
+ .join([context.strip(), *name_slots])
110
+ .format(*expected)
111
+ )
104
112
  if not obj_repr:
105
113
  if not isinstance(err_obj, type):
106
114
  err_obj = type(err_obj)
@@ -122,7 +130,10 @@ def is_matching_type(value, typ):
122
130
  return value in args
123
131
  elif isinstance(typ, TypeVar):
124
132
  if typ.__constraints__:
125
- return any(is_matching_type(value, constraint) for constraint in typ.__constraints__)
133
+ return any(
134
+ is_matching_type(value, constraint)
135
+ for constraint in typ.__constraints__
136
+ )
126
137
  else:
127
138
  return True
128
139
  elif origin is type:
@@ -180,7 +191,9 @@ def is_matching_typed_dict(__d: dict, typed_dict: type[dict]) -> tuple[bool, str
180
191
  field = __d.get(name)
181
192
  if field is None or is_matching_type(field, typ):
182
193
  continue
183
- return False, type_error_msg(field, typ, context=f'keyword argument {name!r} of type')
194
+ return False, type_error_msg(
195
+ field, typ, context=f'keyword argument {name!r} of type'
196
+ )
184
197
  return True, ''
185
198
 
186
199
 
@@ -231,9 +244,9 @@ class _BoundedDict[_KT, _VT](OrderedDict[_KT, _VT]):
231
244
 
232
245
 
233
246
  _SUBTYPE_CACHE: _BoundedDict[int, ...] = _BoundedDict()
234
- _ATTR_GETTERS: _BoundedDict[..., tuple[Callable[[Iterable], NamedTuple], op.attrgetter]] = (
235
- _BoundedDict()
236
- )
247
+ _ATTR_GETTERS: _BoundedDict[
248
+ ..., tuple[Callable[[Iterable], NamedTuple], op.attrgetter]
249
+ ] = _BoundedDict()
237
250
 
238
251
 
239
252
  def _unique_attrs(obj) -> Optional['NamedTuple']:
@@ -278,7 +291,8 @@ def _sort_attrs(obj, tp_name, attr_names):
278
291
  try:
279
292
  sig = inspect.signature(type(obj))
280
293
  indices = (
281
- dict.fromkeys(field_names, inf) | {p: i for i, p in enumerate(sig.parameters)}
294
+ dict.fromkeys(field_names, inf)
295
+ | {p: i for i, p in enumerate(sig.parameters)}
282
296
  ).values()
283
297
  for names in (attr_names, field_names):
284
298
  names.sort(key=dict(zip(names, indices)).__getitem__)
@@ -300,7 +314,9 @@ def _sort_attrs(obj, tp_name, attr_names):
300
314
  while sig_start not in line:
301
315
  line = next(lines)
302
316
  _, _, params = line.partition(sig_start)
303
- params, _, _ = (s.translate(no_square_parens) for s in params.partition(')'))
317
+ params, _, _ = (
318
+ s.translate(no_square_parens) for s in params.partition(')')
319
+ )
304
320
  maybe_sigs.add(params)
305
321
  except StopIteration:
306
322
  break
@@ -308,15 +324,20 @@ def _sort_attrs(obj, tp_name, attr_names):
308
324
  if maybe_sigs:
309
325
  if len(maybe_sigs) > 1:
310
326
  sig = max(
311
- maybe_sigs, key=lambda s: sum(1 for sub in s.split(', ') if sub in field_names)
327
+ maybe_sigs,
328
+ key=lambda s: sum(1 for sub in s.split(', ') if sub in field_names),
312
329
  )
313
330
  else:
314
331
  sig = maybe_sigs.pop()
315
332
  positions = {x: i for i, x in enumerate(sig.split(', ')) if x}
316
333
  sorted_field_names = sorted(field_names, key=lambda k: positions.get(k, inf))
317
- transitions = {idx: sorted_field_names.index(x) for idx, x in enumerate(field_names)}
334
+ transitions = {
335
+ idx: sorted_field_names.index(x) for idx, x in enumerate(field_names)
336
+ }
318
337
  field_names = sorted_field_names
319
- attr_names = [attr_names[k] for k in map(transitions.__getitem__, range(len(attr_names)))]
338
+ attr_names = [
339
+ attr_names[k] for k in map(transitions.__getitem__, range(len(attr_names)))
340
+ ]
320
341
  for Names in (attr_names, field_names):
321
342
  name_attr = next((s for s in Names if s.strip('_') == 'name'), None)
322
343
  if name_attr is not None:
@@ -353,7 +374,9 @@ def subtype[_T](typ: _T) -> _T:
353
374
  args_list = list(args)
354
375
  if (
355
376
  literals := [
356
- idx for idx, elem in enumerate(args) if isinstance(elem, _LiteralGenericType)
377
+ idx
378
+ for idx, elem in enumerate(args)
379
+ if isinstance(elem, _LiteralGenericType)
357
380
  ]
358
381
  ) and len(literals) > 1:
359
382
 
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.3.0'
21
- __version_tuple__ = version_tuple = (0, 3, 0)
20
+ __version__ = version = '0.3.1'
21
+ __version_tuple__ = version_tuple = (0, 3, 1)
@@ -29,7 +29,14 @@ from typing import Final, Literal, SupportsInt, TypeGuard
29
29
 
30
30
  import numpy as np
31
31
 
32
- from .._typing import Float3Tuple, FloatSequence, Int3Tuple, RGBPixel, RGBVectorLike, ShapedNDArray
32
+ from .._typing import (
33
+ Float3Tuple,
34
+ FloatSequence,
35
+ Int3Tuple,
36
+ RGBPixel,
37
+ RGBVectorLike,
38
+ ShapedNDArray,
39
+ )
33
40
 
34
41
 
35
42
  @lru_cache
@@ -107,7 +114,10 @@ def lab2xyz(lab: FloatSequence) -> Float3Tuple:
107
114
  x, y, z = map(
108
115
  mul,
109
116
  (95.047, 100.0, 108.883),
110
- map(lambda i: (lambda j: j if j > 0.008856 else (i - 16 / 116) / 7.787)(i**3), (x, y, z)),
117
+ map(
118
+ lambda i: (lambda j: j if j > 0.008856 else (i - 16 / 116) / 7.787)(i**3),
119
+ (x, y, z),
120
+ ),
111
121
  )
112
122
  return x, y, z
113
123
 
@@ -127,7 +137,9 @@ def rgb2xyz(rgb: RGBPixel) -> Float3Tuple:
127
137
 
128
138
 
129
139
  def xyz2rgb(xyz: ShapedNDArray[tuple[Literal[3]], np.float64]) -> Int3Tuple:
130
- r, g, b = (np.clip(M_XYZ2RGB @ np.array(xyz, dtype=np.float64), 0.0, 1.0) * 255.0).astype(int)
140
+ r, g, b = (
141
+ np.clip(M_XYZ2RGB @ np.array(xyz, dtype=np.float64), 0.0, 1.0) * 255.0
142
+ ).astype(int)
131
143
  return r, g, b
132
144
 
133
145
 
@@ -147,7 +159,13 @@ def hsl2rgb(hsl: FloatSequence) -> Int3Tuple:
147
159
  mid2 = v - vsf
148
160
  r, g, b = (
149
161
  round(x * 0xFF)
150
- for x in [[v, mid1, m], [mid2, v, m], [m, v, mid1], [m, mid2, v], [mid1, m, v]][sextant]
162
+ for x in [
163
+ [v, mid1, m],
164
+ [mid2, v, m],
165
+ [m, v, mid1],
166
+ [m, mid2, v],
167
+ [mid1, m, v],
168
+ ][sextant]
151
169
  )
152
170
  else:
153
171
  r, g, b = [round(L * 0xFF)] * 3
@@ -273,11 +291,13 @@ def _4b_lookup() -> dict[Int3Tuple, Int3Tuple]:
273
291
 
274
292
  rgb_4b_arr = np.asarray(ANSI_4BIT_RGB)
275
293
  quants = np.stack(
276
- np.meshgrid(*np.repeat(np.arange(32).reshape([1, -1]), 3, 0), indexing='ij'), axis=-1
294
+ np.meshgrid(*np.repeat(np.arange(32).reshape([1, -1]), 3, 0), indexing='ij'),
295
+ axis=-1,
277
296
  ).reshape([-1, 3])
278
297
  nearest_colors = rgb_4b_arr[np.argmin(rgb_dist(quants * 8, rgb_4b_arr), axis=1)]
279
298
  table: dict = {
280
- tuple(map(int, color)): tuple(map(int, nearest_colors[i])) for i, color in enumerate(quants)
299
+ tuple(map(int, color)): tuple(map(int, nearest_colors[i]))
300
+ for i, color in enumerate(quants)
281
301
  }
282
302
  return table
283
303
 
@@ -149,7 +149,9 @@ _ANSI16C_I2KV = cast(
149
149
  dict[int, tuple[ColorDictKeys, Int3Tuple]],
150
150
  {
151
151
  v: (k, ansi_4bit_to_rgb(v))
152
- for x in (zip(('fg', 'bg'), (j, j + 10)) for i in (30, 90) for j in range(i, i + 8))
152
+ for x in (
153
+ zip(('fg', 'bg'), (j, j + 10)) for i in (30, 90) for j in range(i, i + 8)
154
+ )
153
155
  for (k, v) in x
154
156
  },
155
157
  )
@@ -391,7 +393,9 @@ AnsiColorFormat: TypeAlias = ansicolor4Bit | ansicolor8Bit | ansicolor24Bit
391
393
  AnsiColorType: TypeAlias = type[AnsiColorFormat]
392
394
  AnsiColorParam: TypeAlias = AnsiColorAlias | AnsiColorType
393
395
  _AnsiColor_co = TypeVar('_AnsiColor_co', bound=colorbytes, covariant=True)
394
- _ANSI_COLOR_TYPES = cast(frozenset[AnsiColorType], frozenset(colorbytes.__subclasses__()))
396
+ _ANSI_COLOR_TYPES = cast(
397
+ frozenset[AnsiColorType], frozenset(colorbytes.__subclasses__())
398
+ )
395
399
  _ANSI_FORMAT_MAP = {k: x for x in _ANSI_COLOR_TYPES for k in [x, x.alias]}
396
400
 
397
401
 
@@ -407,7 +411,9 @@ def _is_ansi_type(typ: type):
407
411
  def sgr_re_pattern():
408
412
  uint8_re = r"(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)"
409
413
  ansicolor_re = f"[3-4]8;(?:2(?:;{uint8_re}){{3}}|5;{uint8_re})"
410
- sgr_param_re = rf"(?:{ansicolor_re}|10[0-7]|9[0-7]|6[0-3]|5[02-5]|2[0-68-9]|[13-4]\d|\d)"
414
+ sgr_param_re = (
415
+ rf"(?:{ansicolor_re}|10[0-7]|9[0-7]|6[0-3]|5[02-5]|2[0-68-9]|[13-4]\d|\d)"
416
+ )
411
417
 
412
418
  return re.compile(rf"\x1b\[(?:{sgr_param_re}(?:;{sgr_param_re})*)?m")
413
419
 
@@ -436,7 +442,10 @@ def _split_ansi_escape(__s: str) -> list[tuple['SgrSequence', str]] | None:
436
442
  out = tmp
437
443
  if out and len(out) % 2 != 0:
438
444
  out.append({SgrSequence: str, str: SgrSequence}[type(out[-1])]())
439
- return [(a, b) if isinstance(a, SgrSequence) else (b, a) for a, b in zip(out[::2], out[1::2])]
445
+ return [
446
+ (a, b) if isinstance(a, SgrSequence) else (b, a)
447
+ for a, b in zip(out[::2], out[1::2])
448
+ ]
440
449
 
441
450
 
442
451
  def _unwrap_ansi_escape(__b: bytes | bytearray):
@@ -458,10 +467,12 @@ def get_ansi_type(typ):
458
467
  from .._typing import unionize
459
468
 
460
469
  repr_getter = lambda t: (t if isinstance(t, type) else type(t))
461
- msg = "Expected {.__name__!r} or {}, got {.__name__!r} object instead".format(
462
- str,
463
- type[unionize(set(map(repr_getter, _ANSI_FORMAT_MAP.values())))],
464
- repr_getter(typ),
470
+ msg = (
471
+ "Expected {.__name__!r} or {}, got {.__name__!r} object instead".format(
472
+ str,
473
+ type[unionize(set(map(repr_getter, _ANSI_FORMAT_MAP.values())))],
474
+ repr_getter(typ),
475
+ )
465
476
  )
466
477
  err = TypeError(msg)
467
478
  err.__cause__ = e.__cause__
@@ -597,10 +608,17 @@ def _get_sgr_nums(__x: bytes) -> list[int]:
597
608
  """
598
609
  if __x.isdigit():
599
610
  return [int(__x)]
600
- __x = __x.removeprefix(CSI)[: idx if ~(idx := __x.find(0x6D)) else None].removesuffix(b'm')
611
+ __x = __x.removeprefix(CSI)[
612
+ : idx if ~(idx := __x.find(0x6D)) else None
613
+ ].removesuffix(b'm')
601
614
  length = len(__x)
602
615
  mask_indices = enumerate(
603
- map(bool, int.to_bytes(~int.from_bytes(b';' * length) & int.from_bytes(__x), length=length))
616
+ map(
617
+ bool,
618
+ int.to_bytes(
619
+ ~int.from_bytes(b';' * length) & int.from_bytes(__x), length=length
620
+ ),
621
+ )
604
622
  )
605
623
  res = []
606
624
  buf = bytearray()
@@ -645,7 +663,9 @@ def _iter_normalized_sgr[_T: (
645
663
  )
646
664
 
647
665
 
648
- def _co_yield_colorbytes(__iter: Iterator[int]) -> Generator[bytes | AnsiColorFormat, int, None]:
666
+ def _co_yield_colorbytes(
667
+ __iter: Iterator[int],
668
+ ) -> Generator[bytes | AnsiColorFormat, int, None]:
649
669
  d: dict[int, ColorDictKeys] = {38: 'fg', 48: 'bg'}
650
670
  obj = b''
651
671
  while True:
@@ -737,7 +757,8 @@ class SgrSequence(MutableSequence[SgrParamBuffer]):
737
757
  def ansi_type(self):
738
758
  if self.is_color():
739
759
  typ, _ = max(
740
- Counter(type(x._value) for x in self if x.is_color()).items(), key=lambda x: x[1]
760
+ Counter(type(x._value) for x in self if x.is_color()).items(),
761
+ key=lambda x: x[1],
741
762
  )
742
763
  return typ
743
764
 
@@ -751,7 +772,8 @@ class SgrSequence(MutableSequence[SgrParamBuffer]):
751
772
  )
752
773
  case ColorStr():
753
774
  return color_chain._from_masks_unchecked(
754
- [(self, ''), (other._sgr, other.base_str)], self.ansi_type() or DEFAULT_ANSI
775
+ [(self, ''), (other._sgr, other.base_str)],
776
+ self.ansi_type() or DEFAULT_ANSI,
755
777
  )
756
778
  case str():
757
779
  return ColorStr(f"{self}{other}")
@@ -831,7 +853,9 @@ class SgrSequence(MutableSequence[SgrParamBuffer]):
831
853
  elts[SgrParamBuffer(elt)] = None
832
854
 
833
855
  self._sgr_params = list(elts)
834
- self._rgb_dict = {k: v for xs in colors.values() for k, v in xs._rgb_dict.items()}
856
+ self._rgb_dict = {
857
+ k: v for xs in colors.values() for k, v in xs._rgb_dict.items()
858
+ }
835
859
 
836
860
  def __iter__(self):
837
861
  return iter(self._sgr_params)
@@ -850,7 +874,9 @@ class SgrSequence(MutableSequence[SgrParamBuffer]):
850
874
  __value: ...
851
875
  xs = list(_iter_sgr(__value))
852
876
  if len(xs) != 1:
853
- err = ValueError(f"parsed {len(xs)} sgr parameters, expected only 1: {xs!r}")
877
+ err = ValueError(
878
+ f"parsed {len(xs)} sgr parameters, expected only 1: {xs!r}"
879
+ )
854
880
  raise err
855
881
  self._sgr_params[__index] = SgrParamBuffer(xs.pop())
856
882
  self._update_colors()
@@ -1009,19 +1035,29 @@ def _make_colorstr[_T: ColorStr](cls: type[_T], obj=_unset, *args, **kwargs) ->
1009
1035
  else:
1010
1036
  [typ] = e.args
1011
1037
  err = TypeError(
1012
- "expected integer or vector of 3 integers, " f"got {typ.__name__!r} object instead"
1038
+ "expected integer or vector of 3 integers, "
1039
+ f"got {typ.__name__!r} object instead"
1013
1040
  )
1014
1041
  err.__cause__ = e.__cause__
1015
1042
  raise err
1016
- inst: Any = str.__new__(cls, ''.join([str(sgr), base_str, SGR_RESET_S if reset else '']))
1017
- inst.__dict__ |= {'_sgr': sgr, '_base_str': base_str, '_ansi_type': ansi_type, '_reset': reset}
1043
+ inst: Any = str.__new__(
1044
+ cls, ''.join([str(sgr), base_str, SGR_RESET_S if reset else ''])
1045
+ )
1046
+ inst.__dict__ |= {
1047
+ '_sgr': sgr,
1048
+ '_base_str': base_str,
1049
+ '_ansi_type': ansi_type,
1050
+ '_reset': reset,
1051
+ }
1018
1052
  return inst
1019
1053
 
1020
1054
 
1021
1055
  class ColorStr(str):
1022
1056
  def _weak_var_update(self, **kwargs):
1023
1057
  if not kwargs.keys() <= {'base_str', 'sgr', 'reset'}:
1024
- raise ValueError(f'unexpected keys: {(kwargs.keys() - {'base_str', 'sgr', 'reset'})}')
1058
+ raise ValueError(
1059
+ f'unexpected keys: {(kwargs.keys() - {'base_str', 'sgr', 'reset'})}'
1060
+ )
1025
1061
  sgr = kwargs.get('sgr', self._sgr)
1026
1062
  base_str = kwargs.get('base_str', self.base_str)
1027
1063
  suffix = SGR_RESET_S if kwargs.get('reset', self.reset) else ''
@@ -1055,7 +1091,8 @@ class ColorStr(str):
1055
1091
  sgr = SgrSequence(self._sgr)
1056
1092
  sgr.rgb_dict = sgr._rgb_dict, ansi_type
1057
1093
  inst = str.__new__(
1058
- type(self), ''.join([str(sgr), self.base_str, SGR_RESET_S if self.reset else ''])
1094
+ type(self),
1095
+ ''.join([str(sgr), self.base_str, SGR_RESET_S if self.reset else '']),
1059
1096
  )
1060
1097
  inst.__dict__ |= vars(self) | {'_sgr': sgr, '_ansi_type': ansi_type}
1061
1098
  return inst
@@ -1122,7 +1159,9 @@ class ColorStr(str):
1122
1159
  ('Red text', '0x00FF00')
1123
1160
  """
1124
1161
  if not kwargs.keys() <= {'absolute', 'fg', 'bg'}:
1125
- raise ValueError(f"unexpected keywords: {(kwargs.keys() - {'absolute', 'fg', 'bg'})}")
1162
+ raise ValueError(
1163
+ f"unexpected keywords: {(kwargs.keys() - {'absolute', 'fg', 'bg'})}"
1164
+ )
1126
1165
  if kwargs.pop('absolute', False):
1127
1166
  if not (args or kwargs):
1128
1167
  return (
@@ -1167,14 +1206,18 @@ class ColorStr(str):
1167
1206
  if b'%d' % SgrParameter.DOUBLE_UNDERLINE in self._sgr:
1168
1207
  return self
1169
1208
  elif b'%d' % SgrParameter.SINGLE_UNDERLINE in self._sgr:
1170
- return self.update_sgr(SgrParameter.SINGLE_UNDERLINE, SgrParameter.DOUBLE_UNDERLINE)
1209
+ return self.update_sgr(
1210
+ SgrParameter.SINGLE_UNDERLINE, SgrParameter.DOUBLE_UNDERLINE
1211
+ )
1171
1212
  else:
1172
1213
  return self.update_sgr(SgrParameter.DOUBLE_UNDERLINE)
1173
1214
  else:
1174
1215
  if b'%d' % SgrParameter.SINGLE_UNDERLINE in self._sgr:
1175
1216
  return self
1176
1217
  elif b'%d' % SgrParameter.DOUBLE_UNDERLINE in self._sgr:
1177
- return self.update_sgr(SgrParameter.DOUBLE_UNDERLINE, SgrParameter.SINGLE_UNDERLINE)
1218
+ return self.update_sgr(
1219
+ SgrParameter.DOUBLE_UNDERLINE, SgrParameter.SINGLE_UNDERLINE
1220
+ )
1178
1221
  else:
1179
1222
  return self.update_sgr(SgrParameter.SINGLE_UNDERLINE)
1180
1223
 
@@ -1245,7 +1288,8 @@ class ColorStr(str):
1245
1288
  else:
1246
1289
  sgr.append(bx)
1247
1290
  inst = super().__new__(
1248
- type(self), ''.join([str(sgr), self.base_str, SGR_RESET_S if self.reset else ''])
1291
+ type(self),
1292
+ ''.join([str(sgr), self.base_str, SGR_RESET_S if self.reset else '']),
1249
1293
  )
1250
1294
  inst.__dict__ |= vars(self) | {
1251
1295
  '_sgr': sgr,
@@ -1321,7 +1365,9 @@ class ColorStr(str):
1321
1365
 
1322
1366
  def join(self, __iterable):
1323
1367
  return self._weak_var_update(
1324
- base_str=self.base_str.join(getattr(elt, 'base_str', elt) for elt in __iterable)
1368
+ base_str=self.base_str.join(
1369
+ getattr(elt, 'base_str', elt) for elt in __iterable
1370
+ )
1325
1371
  )
1326
1372
 
1327
1373
  def ljust(self, __width, __fillchar=" "):
@@ -1334,7 +1380,9 @@ class ColorStr(str):
1334
1380
  return self._weak_var_update(base_str=self.base_str.lstrip(__chars))
1335
1381
 
1336
1382
  def partition(self, __sep):
1337
- lhs, sep, rhs = (self._weak_var_update(base_str=s) for s in self.base_str.partition(__sep))
1383
+ lhs, sep, rhs = (
1384
+ self._weak_var_update(base_str=s) for s in self.base_str.partition(__sep)
1385
+ )
1338
1386
  return lhs, sep, rhs
1339
1387
 
1340
1388
  def removeprefix(self, __prefix):
@@ -1344,7 +1392,9 @@ class ColorStr(str):
1344
1392
  return self._weak_var_update(base_str=self.base_str.removesuffix(__prefix))
1345
1393
 
1346
1394
  def replace(self, __old, __new, __count=-1):
1347
- return self._weak_var_update(base_str=self.base_str.replace(__old, __new, __count))
1395
+ return self._weak_var_update(
1396
+ base_str=self.base_str.replace(__old, __new, __count)
1397
+ )
1348
1398
 
1349
1399
  def rfind(self, __sub, *args):
1350
1400
  return self.base_str.rfind(__sub, *args)
@@ -1359,7 +1409,9 @@ class ColorStr(str):
1359
1409
  return self._weak_var_update(base_str=self.base_str.rstrip(__chars))
1360
1410
 
1361
1411
  def rpartition(self, __sep):
1362
- lhs, sep, rhs = (self._weak_var_update(base_str=s) for s in self.base_str.rpartition(__sep))
1412
+ lhs, sep, rhs = (
1413
+ self._weak_var_update(base_str=s) for s in self.base_str.rpartition(__sep)
1414
+ )
1363
1415
  return lhs, sep, rhs
1364
1416
 
1365
1417
  def rsplit(self, sep=None, maxsplit=-1):
@@ -1376,7 +1428,8 @@ class ColorStr(str):
1376
1428
 
1377
1429
  def splitlines(self, keepends=False):
1378
1430
  return [
1379
- self._weak_var_update(base_str=s) for s in self.base_str.splitlines(keepends=keepends)
1431
+ self._weak_var_update(base_str=s)
1432
+ for s in self.base_str.splitlines(keepends=keepends)
1380
1433
  ]
1381
1434
 
1382
1435
  def startswith(self, __prefix, *args):
@@ -1476,11 +1529,15 @@ class ColorStr(str):
1476
1529
  k: L['fg', 'bg']
1477
1530
  if isinstance(other, type(self)):
1478
1531
  xor_dict = {
1479
- k: int2rgb(Color.from_rgb(self.rgb_dict[k]) ^ Color.from_rgb(other.rgb_dict[k]))
1532
+ k: int2rgb(
1533
+ Color.from_rgb(self.rgb_dict[k]) ^ Color.from_rgb(other.rgb_dict[k])
1534
+ )
1480
1535
  for k in self.rgb_dict.keys() & other.rgb_dict
1481
1536
  }
1482
1537
  elif isinstance(other, int):
1483
- xor_dict = {k: int2rgb(Color.from_rgb(v) ^ other) for k, v in self.rgb_dict.items()}
1538
+ xor_dict = {
1539
+ k: int2rgb(Color.from_rgb(v) ^ other) for k, v in self.rgb_dict.items()
1540
+ }
1484
1541
  else:
1485
1542
  return NotImplemented
1486
1543
  if not xor_dict:
@@ -1596,7 +1653,10 @@ class color_chain:
1596
1653
  elif isinstance(other, str):
1597
1654
  if len(self._masks) > 0:
1598
1655
  return self._from_masks_unchecked(
1599
- [*self.masks[:-1], (self._masks[-1][0], self._masks[-1][1] + other)],
1656
+ [
1657
+ *self.masks[:-1],
1658
+ (self._masks[-1][0], self._masks[-1][1] + other),
1659
+ ],
1600
1660
  ansi_type=self._ansi_type,
1601
1661
  )
1602
1662
  return self._from_masks_unchecked(
@@ -1615,7 +1675,9 @@ class color_chain:
1615
1675
  if not kwargs.keys() <= {'fg', 'bg'}:
1616
1676
  raise ValueError
1617
1677
  sgr = SgrSequence(__sgr)
1618
- sgr.rgb_dict = {k: v for k, v in kwargs.items() if v is not None}, self._ansi_type
1678
+ sgr.rgb_dict = {
1679
+ k: v for k, v in kwargs.items() if v is not None
1680
+ }, self._ansi_type
1619
1681
  self._masks = [(sgr, '')]
1620
1682
 
1621
1683
  def __radd__(self, other):
@@ -96,7 +96,9 @@ class colorbytes(bytes):
96
96
  RGBVectorLike,
97
97
  )](
98
98
  cls: type[_T],
99
- __rgb: tuple[ColorDictKeys, _VT] | Mapping[L['fg'], _VT] | Mapping[L['bg'], _VT],
99
+ __rgb: (
100
+ tuple[ColorDictKeys, _VT] | Mapping[L['fg'], _VT] | Mapping[L['bg'], _VT]
101
+ ),
100
102
  ) -> _T: ...
101
103
  @classmethod
102
104
  @overload
@@ -118,7 +120,9 @@ class colorbytes(bytes):
118
120
  @property
119
121
  def rgb_dict(
120
122
  self,
121
- ) -> MappingProxyType[L['fg'], Int3Tuple] | MappingProxyType[L['bg'], Int3Tuple]: ...
123
+ ) -> (
124
+ MappingProxyType[L['fg'], Int3Tuple] | MappingProxyType[L['bg'], Int3Tuple]
125
+ ): ...
122
126
 
123
127
  class ColorStr(str):
124
128
  def _weak_var_update(self, **kwargs: Unpack[_ColorStrWeakVars]) -> Self: ...
@@ -138,7 +142,11 @@ class ColorStr(str):
138
142
  def casefold(self) -> Self: ...
139
143
  def center(self, width, fillchar=' ') -> Self: ...
140
144
  def count(
141
- self, x: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ..., /
145
+ self,
146
+ x: str,
147
+ __start: SupportsIndex | None = ...,
148
+ __end: SupportsIndex | None = ...,
149
+ /,
142
150
  ): ...
143
151
  def endswith(
144
152
  self,
@@ -149,12 +157,20 @@ class ColorStr(str):
149
157
  ) -> bool: ...
150
158
  def expandtabs(self, /, tabsize=8) -> Self: ...
151
159
  def find(
152
- self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ..., /
160
+ self,
161
+ __sub: str,
162
+ __start: SupportsIndex | None = ...,
163
+ __end: SupportsIndex | None = ...,
164
+ /,
153
165
  ) -> int: ...
154
166
  def format(self, *args, **kwargs) -> Self: ...
155
167
  def format_map(self, __mapping: Mapping[str, object], /) -> Self: ...
156
168
  def index(
157
- self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ..., /
169
+ self,
170
+ __sub: str,
171
+ __start: SupportsIndex | None = ...,
172
+ __end: SupportsIndex | None = ...,
173
+ /,
158
174
  ) -> int: ...
159
175
  def join(self, __iterable: Iterable[str]) -> Self: ...
160
176
  def ljust(self, __width: SupportsIndex, __fillchar=' ') -> Self: ...
@@ -165,10 +181,18 @@ class ColorStr(str):
165
181
  def removesuffix(self, __suffix: str, /) -> Self: ...
166
182
  def replace(self, __old: str, __new: str, __count: SupportsIndex = -1) -> Self: ...
167
183
  def rfind(
168
- self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ..., /
184
+ self,
185
+ __sub: str,
186
+ __start: SupportsIndex | None = ...,
187
+ __end: SupportsIndex | None = ...,
188
+ /,
169
189
  ) -> int: ...
170
190
  def rindex(
171
- self, __sub: str, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ..., /
191
+ self,
192
+ __sub: str,
193
+ __start: SupportsIndex | None = ...,
194
+ __end: SupportsIndex | None = ...,
195
+ /,
172
196
  ) -> int: ...
173
197
  def rjust(self, __width: SupportsIndex, __fillchar=' ') -> Self: ...
174
198
  def rpartition(self, __sep: str) -> TupleOf3[Self]: ...
@@ -255,16 +279,30 @@ class color_chain:
255
279
  ) -> Self: ...
256
280
  @classmethod
257
281
  def from_masks(
258
- cls, masks: Sequence[tuple[SgrSequence, str]], ansi_type: type[AnsiColorFormat] = None
282
+ cls,
283
+ masks: Sequence[tuple[SgrSequence, str]],
284
+ ansi_type: type[AnsiColorFormat] = None,
259
285
  ) -> Self: ...
260
- def __add__[_T: (color_chain, SgrSequence, ColorStr, str)](self, other: _T) -> color_chain: ...
286
+ def __add__[_T: (
287
+ color_chain,
288
+ SgrSequence,
289
+ ColorStr,
290
+ str,
291
+ )](self, other: _T) -> color_chain: ...
261
292
  def __call__(self, __obj=None) -> str: ...
262
293
  def __init__[_T: (
263
294
  int,
264
295
  Buffer,
265
296
  SgrParamBuffer,
266
- )](self, __sgr: Iterable[_T] = ..., **kwargs: Unpack[_ColorChainKwargs]) -> None: ...
267
- def __radd__[_T: (color_chain, SgrSequence, ColorStr, str)](self, other: _T) -> color_chain: ...
297
+ )](
298
+ self, __sgr: Iterable[_T] = ..., **kwargs: Unpack[_ColorChainKwargs]
299
+ ) -> None: ...
300
+ def __radd__[_T: (
301
+ color_chain,
302
+ SgrSequence,
303
+ ColorStr,
304
+ str,
305
+ )](self, other: _T) -> color_chain: ...
268
306
 
269
307
  _ansi_type: type[AnsiColorFormat]
270
308
  _masks: list[tuple[SgrSequence, str]]
@@ -355,7 +393,9 @@ class SgrParamBuffer[
355
393
  def is_reset(self) -> bool: ...
356
394
  def __buffer__(self, __flags: int) -> memoryview: ...
357
395
  def __bytes__(self) -> bytes: ...
358
- def __eq__[_T](self: SgrParamBuffer[_T], other) -> TypeIs[SgrParamBuffer[_T] | _T]: ...
396
+ def __eq__[_T](
397
+ self: SgrParamBuffer[_T], other
398
+ ) -> TypeIs[SgrParamBuffer[_T] | _T]: ...
359
399
  def __hash__(self) -> int: ...
360
400
  @overload
361
401
  def __new__(cls, __value: _T = ...) -> Self: ...
@@ -394,14 +434,20 @@ class SgrSequence(MutableSequence[SgrParamBuffer]):
394
434
  @overload
395
435
  def __getitem__(self, __index: SupportsIndex) -> SgrParamBuffer: ...
396
436
  @overload
397
- def __setitem__(self, __index: slice, __value: Iterable[bytes | SgrParamBuffer]): ...
437
+ def __setitem__(
438
+ self, __index: slice, __value: Iterable[bytes | SgrParamBuffer]
439
+ ): ...
398
440
  @overload
399
441
  def __setitem__(self, __index: SupportsIndex, __value: bytes | SgrParamBuffer): ...
400
442
  @overload
401
443
  def __delitem__(self, __index: slice): ...
402
444
  @overload
403
445
  def __delitem__(self, __index: SupportsIndex): ...
404
- def __init__[_T: (int, Buffer, SgrParamBuffer)](self, __iter: Iterable[_T] = ...): ...
446
+ def __init__[_T: (
447
+ int,
448
+ Buffer,
449
+ SgrParamBuffer,
450
+ )](self, __iter: Iterable[_T] = ...): ...
405
451
  def __iter__(self) -> Iterator[SgrParamBuffer]: ...
406
452
 
407
453
  __slots__ = '_rgb_dict', '_sgr_params'
@@ -421,7 +467,9 @@ class SgrSequence(MutableSequence[SgrParamBuffer]):
421
467
  def rgb_dict(self, __value: dict[ColorDictKeys, Int3Tuple | None]): ...
422
468
  @overload
423
469
  @rgb_dict.setter # type: ignore[no-redef]
424
- def rgb_dict(self, __value: tuple[dict[ColorDictKeys, Int3Tuple | None], AnsiColorType]): ...
470
+ def rgb_dict(
471
+ self, __value: tuple[dict[ColorDictKeys, Int3Tuple | None], AnsiColorType]
472
+ ): ...
425
473
 
426
474
  class _RecolorKwargs(TypedDict, total=False):
427
475
  absolute: bool