dtools.circular-array 3.10.1__py3-none-any.whl → 3.11.0__py3-none-any.whl

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.
@@ -17,13 +17,18 @@
17
17
  Package for an indexable, sliceable, auto-resizing circular array
18
18
  data structure with amortized O(1) pushes and pops either end.
19
19
 
20
- #### Modules
20
+ #### Circular Array Data Structure
21
21
 
22
- * module dtools.circular_array.ca: circular array data structure
22
+ * *module* dtools.circular_array.ca
23
+ * circular array data structure
24
+ * *class* dtools.circular_array.ca.CA
25
+ * initializer takes 1 or 0 iterables
26
+ * *function* dtools.circular_array.ca.ca
27
+ * factory function taking a variable number of arguments
23
28
 
24
29
  """
25
30
 
26
- __version__ = '3.10.1'
31
+ __version__ = '3.11.0'
27
32
  __author__ = 'Geoffrey R. Scheller'
28
33
  __copyright__ = 'Copyright (c) 2023-2025 Geoffrey R. Scheller'
29
34
  __license__ = 'Apache License 2.0'
@@ -18,15 +18,15 @@ from __future__ import annotations
18
18
  from collections.abc import Callable, Iterable, Iterator, Sequence
19
19
  from typing import cast, Never, overload, TypeVar
20
20
 
21
- __all__ = ['ca', 'CA']
21
+ __all__ = ['CA', 'ca']
22
22
 
23
- D = TypeVar('D') # Not needed for mypy, hint for pdoc.
24
- L = TypeVar('L')
25
- R = TypeVar('R')
26
- U = TypeVar('U')
23
+ D = TypeVar('D') # type: ignore[unused-ignore] # Needed only for pdoc
24
+ L = TypeVar('L') # type: ignore[unused-ignore] # documentation generation.
25
+ R = TypeVar('R') # type: ignore[unused-ignore] # Otherwise, not needed
26
+ U = TypeVar('U') # type: ignore[unused-ignore] # by either MyPy or Python.
27
27
 
28
28
 
29
- class ca[D](Sequence[D]):
29
+ class CA[D](Sequence[D]):
30
30
  """Indexable circular array data structure
31
31
 
32
32
  - generic, stateful data structure
@@ -52,7 +52,7 @@ class ca[D](Sequence[D]):
52
52
  [None] + cast(list[D | None], list(*dss)) + [None]
53
53
  )
54
54
  else:
55
- msg = f'ca expected at most 1 argument, got {len(dss)}'
55
+ msg = f'CA expected at most 1 argument, got {len(dss)}'
56
56
  raise TypeError(msg)
57
57
  self._cap = cap = len(self._data)
58
58
  self._cnt = cap - 2
@@ -76,7 +76,7 @@ class ca[D](Sequence[D]):
76
76
  self._front, self._cap = self._front + self._cap, 2 * self._cap
77
77
 
78
78
  def _compact_storage_capacity(self) -> None:
79
- """Compact the ca."""
79
+ """Compact the CA."""
80
80
  match self._cnt:
81
81
  case 0:
82
82
  self._cap, self._front, self._rear, self._data = 2, 0, 1, [None, None]
@@ -135,7 +135,7 @@ class ca[D](Sequence[D]):
135
135
  yield cast(D, current_state[position])
136
136
 
137
137
  def __repr__(self) -> str:
138
- return 'CA(' + ', '.join(map(repr, self)) + ')'
138
+ return 'ca(' + ', '.join(map(repr, self)) + ')'
139
139
 
140
140
  def __str__(self) -> str:
141
141
  return '(|' + ', '.join(map(str, self)) + '|)'
@@ -149,11 +149,11 @@ class ca[D](Sequence[D]):
149
149
  @overload
150
150
  def __getitem__(self, idx: int, /) -> D: ...
151
151
  @overload
152
- def __getitem__(self, idx: slice, /) -> ca[D]: ...
152
+ def __getitem__(self, idx: slice, /) -> CA[D]: ...
153
153
 
154
- def __getitem__(self, idx: int | slice, /) -> D | ca[D]:
154
+ def __getitem__(self, idx: int | slice, /) -> D | CA[D]:
155
155
  if isinstance(idx, slice):
156
- return ca(list(self)[idx])
156
+ return CA(list(self)[idx])
157
157
 
158
158
  cnt = self._cnt
159
159
  if 0 <= idx < cnt:
@@ -163,12 +163,12 @@ class ca[D](Sequence[D]):
163
163
  return cast(D, self._data[(self._front + cnt + idx) % self._cap])
164
164
 
165
165
  if cnt == 0:
166
- msg0 = 'Trying to get a value from an empty ca.'
166
+ msg0 = 'Trying to get a value from an empty CA.'
167
167
  raise IndexError(msg0)
168
168
 
169
169
  msg1 = 'Out of bounds: '
170
170
  msg2 = f'index = {idx} not between {-cnt} and {cnt - 1} '
171
- msg3 = 'while getting value from a ca.'
171
+ msg3 = 'while getting value from a CA.'
172
172
  raise IndexError(msg1 + msg2 + msg3)
173
173
 
174
174
  @overload
@@ -181,7 +181,7 @@ class ca[D](Sequence[D]):
181
181
  if isinstance(vals, Iterable):
182
182
  data = list(self)
183
183
  data[idx] = vals
184
- _ca = ca(data)
184
+ _ca = CA(data)
185
185
  self._data, self._cnt, self._cap, self._front, self._rear = (
186
186
  _ca._data,
187
187
  _ca._cnt,
@@ -201,12 +201,12 @@ class ca[D](Sequence[D]):
201
201
  self._data[(self._front + cnt + idx) % self._cap] = cast(D, vals)
202
202
  else:
203
203
  if cnt < 1:
204
- msg0 = 'Trying to set a value from an empty ca.'
204
+ msg0 = 'Trying to set a value from an empty CA.'
205
205
  raise IndexError(msg0)
206
206
 
207
207
  msg1 = 'Out of bounds: '
208
208
  msg2 = f'index = {idx} not between {-cnt} and {cnt - 1} '
209
- msg3 = 'while setting value from a ca.'
209
+ msg3 = 'while setting value from a CA.'
210
210
  raise IndexError(msg1 + msg2 + msg3)
211
211
 
212
212
  @overload
@@ -217,7 +217,7 @@ class ca[D](Sequence[D]):
217
217
  def __delitem__(self, idx: int | slice) -> None:
218
218
  data = list(self)
219
219
  del data[idx]
220
- _ca = ca(data)
220
+ _ca = CA(data)
221
221
  self._data, self._cnt, self._cap, self._front, self._rear = (
222
222
  _ca._data,
223
223
  _ca._cnt,
@@ -258,7 +258,7 @@ class ca[D](Sequence[D]):
258
258
  return True
259
259
 
260
260
  def pushl(self, *ds: D) -> None:
261
- """Push data from the left onto the ca."""
261
+ """Push data from the left onto the CA."""
262
262
  for d in ds:
263
263
  if self._cnt == self._cap:
264
264
  self._double_storage_capacity()
@@ -266,7 +266,7 @@ class ca[D](Sequence[D]):
266
266
  self._data[self._front], self._cnt = d, self._cnt + 1
267
267
 
268
268
  def pushr(self, *ds: D) -> None:
269
- """Push data from the right onto the ca."""
269
+ """Push data from the right onto the CA."""
270
270
  for d in ds:
271
271
  if self._cnt == self._cap:
272
272
  self._double_storage_capacity()
@@ -274,9 +274,9 @@ class ca[D](Sequence[D]):
274
274
  self._data[self._rear], self._cnt = d, self._cnt + 1
275
275
 
276
276
  def popl(self) -> D | Never:
277
- """Pop one value off the left side of the ca.
277
+ """Pop one value off the left side of the CA.
278
278
 
279
- Raises `ValueError` when called on an empty ca.
279
+ Raises `ValueError` when called on an empty CA.
280
280
 
281
281
  """
282
282
  if self._cnt > 1:
@@ -295,14 +295,14 @@ class ca[D](Sequence[D]):
295
295
  self._cap - 1,
296
296
  )
297
297
  else:
298
- msg = 'Method popl called on an empty ca'
298
+ msg = 'Method popl called on an empty CA'
299
299
  raise ValueError(msg)
300
300
  return cast(D, d)
301
301
 
302
302
  def popr(self) -> D | Never:
303
- """Pop one value off the right side of the ca.
303
+ """Pop one value off the right side of the CA.
304
304
 
305
- Raises `ValueError` when called on an empty ca.
305
+ Raises `ValueError` when called on an empty CA.
306
306
 
307
307
  """
308
308
  if self._cnt > 1:
@@ -321,7 +321,7 @@ class ca[D](Sequence[D]):
321
321
  self._cap - 1,
322
322
  )
323
323
  else:
324
- msg = 'Method popr called on an empty ca'
324
+ msg = 'Method popr called on an empty CA'
325
325
  raise ValueError(msg)
326
326
  return cast(D, d)
327
327
 
@@ -329,7 +329,7 @@ class ca[D](Sequence[D]):
329
329
  """Pop one value from left, provide a mandatory default value.
330
330
 
331
331
  - safe version of popl
332
- - returns a default value in the event the `ca` is empty
332
+ - returns a default value in the event the `CA` is empty
333
333
 
334
334
  """
335
335
  try:
@@ -341,7 +341,7 @@ class ca[D](Sequence[D]):
341
341
  """Pop one value from right, provide a mandatory default value.
342
342
 
343
343
  - safe version of popr
344
- - returns a default value in the event the `ca` is empty
344
+ - returns a default value in the event the `CA` is empty
345
345
 
346
346
  """
347
347
  try:
@@ -349,34 +349,34 @@ class ca[D](Sequence[D]):
349
349
  except ValueError:
350
350
  return default
351
351
 
352
- def poplt(self, max: int) -> tuple[D, ...]:
353
- """Pop multiple values from left side of ca.
352
+ def poplt(self, maximum: int) -> tuple[D, ...]:
353
+ """Pop multiple values from left side of `CA`.
354
354
 
355
355
  - returns the results in a tuple of type `tuple[~D, ...]`
356
- - returns an empty tuple if `ca` is empty
356
+ - returns an empty tuple if `CA` is empty
357
357
  - pop no more that `max` values
358
- - will pop less if `ca` becomes empty
358
+ - will pop less if `CA` becomes empty
359
359
 
360
360
  """
361
361
  ds: list[D] = []
362
362
 
363
- while max > 0:
363
+ while maximum > 0:
364
364
  try:
365
365
  ds.append(self.popl())
366
366
  except ValueError:
367
367
  break
368
368
  else:
369
- max -= 1
369
+ maximum -= 1
370
370
 
371
371
  return tuple(ds)
372
372
 
373
373
  def poprt(self, max: int) -> tuple[D, ...]:
374
- """Pop multiple values from right side of `ca`.
374
+ """Pop multiple values from right side of `CA`.
375
375
 
376
376
  - returns the results in a tuple of type `tuple[~D, ...]`
377
- - returns an empty tuple if `ca` is empty
377
+ - returns an empty tuple if `CA` is empty
378
378
  - pop no more that `max` values
379
- - will pop less if `ca` becomes empty
379
+ - will pop less if `CA` becomes empty
380
380
 
381
381
  """
382
382
  ds: list[D] = []
@@ -391,7 +391,7 @@ class ca[D](Sequence[D]):
391
391
  return tuple(ds)
392
392
 
393
393
  def rotl(self, n: int = 1) -> None:
394
- """Rotate ca arguments left n times."""
394
+ """Rotate `CA` arguments left n times."""
395
395
  if self._cnt < 2:
396
396
  return
397
397
  while n > 0:
@@ -399,24 +399,24 @@ class ca[D](Sequence[D]):
399
399
  n -= 1
400
400
 
401
401
  def rotr(self, n: int = 1) -> None:
402
- """Rotate ca arguments right n times."""
402
+ """Rotate `CA` arguments right n times."""
403
403
  if self._cnt < 2:
404
404
  return
405
405
  while n > 0:
406
406
  self.pushl(self.popr())
407
407
  n -= 1
408
408
 
409
- def map[U](self, f: Callable[[D], U], /) -> ca[U]:
410
- """Apply function f over contents, returns new `ca` instance.
409
+ def map[U](self, f: Callable[[D], U], /) -> CA[U]:
410
+ """Apply function f over contents, returns new `CA` instance.
411
411
 
412
- - parameter `f` function of type `f[~D, ~U] -> ca[~U]`
413
- - returns a new instance of type `ca[~U]`
412
+ - parameter `f` function of type `f[~D, ~U] -> CA[~U]`
413
+ - returns a new instance of type `CA[~U]`
414
414
 
415
415
  """
416
- return ca(map(f, self))
416
+ return CA(map(f, self))
417
417
 
418
418
  def foldl[L](self, f: Callable[[L, D], L], /, initial: L | None = None) -> L:
419
- """Left fold ca via function and optional initial value.
419
+ """Left fold `CA` via function and optional initial value.
420
420
 
421
421
  - parameter `f` function of type `f[~L, ~D] -> ~L`
422
422
  - the first argument to `f` is for the accumulated value.
@@ -429,7 +429,7 @@ class ca[D](Sequence[D]):
429
429
  """
430
430
  if self._cnt == 0:
431
431
  if initial is None:
432
- msg = 'Method foldL called on an empty ca without an initial value.'
432
+ msg = 'Method foldl called on an empty `CA` without an initial value.'
433
433
  raise ValueError(msg)
434
434
  return initial
435
435
 
@@ -445,7 +445,7 @@ class ca[D](Sequence[D]):
445
445
  return acc
446
446
 
447
447
  def foldr[R](self, f: Callable[[D, R], R], /, initial: R | None = None) -> R:
448
- """Right fold ca via function and optional initial value.
448
+ """Right fold `CA` via function and optional initial value.
449
449
 
450
450
  - parameter `f` function of type `f[~D, ~R] -> ~R`
451
451
  - the second argument to f is for the accumulated value
@@ -453,12 +453,12 @@ class ca[D](Sequence[D]):
453
453
  - returns the reduced value of type `~R`
454
454
  - note that `~R` and `~D` can be the same type
455
455
  - if an initial value is not given then by necessity `~R = ~D`
456
- - raises `ValueError` when called on an empty `ca` and `initial` not given
456
+ - raises `ValueError` when called on an empty `CA` and `initial` not given
457
457
 
458
458
  """
459
459
  if self._cnt == 0:
460
460
  if initial is None:
461
- msg = 'Method foldr called on an empty ca without an initial value.'
461
+ msg = 'Method foldr called on empty `CA` without initial value.'
462
462
  raise ValueError(msg)
463
463
  return initial
464
464
 
@@ -474,21 +474,21 @@ class ca[D](Sequence[D]):
474
474
  return acc
475
475
 
476
476
  def capacity(self) -> int:
477
- """Returns current capacity of the ca."""
477
+ """Returns current capacity of the `CA`."""
478
478
  return self._cap
479
479
 
480
480
  def empty(self) -> None:
481
- """Empty the ca, keep current capacity."""
481
+ """Empty the `CA`, keep current capacity."""
482
482
  self._data, self._front, self._rear = [None] * self._cap, 0, self._cap
483
483
 
484
484
  def fraction_filled(self) -> float:
485
- """Returns fractional capacity of the ca."""
485
+ """Returns fractional capacity of the `CA`."""
486
486
  return self._cnt / self._cap
487
487
 
488
488
  def resize(self, minimum_capacity: int = 2) -> None:
489
- """Compact `ca` and resize to `minimum_capacity` if necessary.
489
+ """Compact `CA` and resize to `minimum_capacity` if necessary.
490
490
 
491
- To just compact the `ca`, do not provide a minimum capacity.
491
+ To just compact the `CA`, do not provide a minimum capacity.
492
492
 
493
493
  """
494
494
  self._compact_storage_capacity()
@@ -498,11 +498,6 @@ class ca[D](Sequence[D]):
498
498
  self._front, self._rear = 0, self._cap - 1
499
499
 
500
500
 
501
- def CA[D](*ds: D) -> ca[D]:
502
- """Function to produce a `ca` array from a variable number of arguments.
503
-
504
- Upper case function name used to stand out in place of syntactic sugar
505
- used by builtins, like `[]` for list or `{}` for dict or set.
506
-
507
- """
508
- return ca(ds)
501
+ def ca[D](*ds: D) -> CA[D]:
502
+ """Function to produce a `CA` array from a variable number of arguments."""
503
+ return CA(ds)
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dtools.circular-array
3
- Version: 3.10.1
3
+ Version: 3.11.0
4
4
  Summary: ### Developer Tools - circular array data structure
5
- Keywords: circular array,circle array,ca,double ended queue,dequeue,dqueue,pop,push,popl,popr,pushl,pushr,indexable,auto-resizing,auto resizing,resizing
5
+ Keywords: circular array,circle array,CA,dequeue,dqueue,FIFO,LIFO,pop,push,indexable,auto-resizing,auto resizing,resizing
6
6
  Author-email: "Geoffrey R. Scheller" <geoffrey@scheller.com>
7
7
  Requires-Python: >=3.12
8
8
  Description-Content-Type: text/markdown
@@ -63,36 +63,35 @@ syntactic sugar like `[]` or `{}`.
63
63
  ```python
64
64
  from dtools.circular_array.ca import CA
65
65
 
66
- ca = CA(1, 2, 3)
67
- assert ca.popl() == 1
68
- assert ca.popr() == 3
69
- ca.pushr(42, 0)
70
- ca.pushl(0, 1)
71
- assert repr(ca) == 'CA(1, 0, 2, 42, 0)'
72
- assert str(ca) == '(|1, 0, 2, 42, 0|)'
66
+ ca1 = ca(1, 2, 3)
67
+ assert ca1.popl() == 1
68
+ assert ca1.popr() == 3
69
+ ca1.pushr(42, 0)
70
+ ca1.pushl(0, 1)
71
+ assert repr(ca1) == 'ca(1, 0, 2, 42, 0)'
72
+ assert str(ca1) == '(|1, 0, 2, 42, 0|)'
73
73
 
74
- ca = ca(range(1,11))
75
- assert repr(ca) == 'CA(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)'
76
- assert str(ca) == '(|1, 2, 3, 4, 5, 6, 7, 8, 9, 10|)'
77
- assert len(ca) == 10
78
- tup3 = ca.poplt(3)
79
- tup4 = ca.poprt(4)
74
+ ca2 = CA(range(1,11))
75
+ assert repr(ca2) == 'ca(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)'
76
+ assert str(ca2) == '(|1, 2, 3, 4, 5, 6, 7, 8, 9, 10|)'
77
+ assert len(ca2) == 10
78
+ tup3 = ca2.poplt(3)
79
+ tup4 = ca2.poprt(4)
80
80
  assert tup3 == (1, 2, 3)
81
81
  assert tup4 == (10, 9, 8, 7)
82
-
83
- assert ca == CA(4, 5, 6)
82
+ assert ca2 == CA(4, 5, 6)
84
83
  four, *rest = ca.popft(1000)
85
84
  assert four == 4
86
85
  assert rest == [5, 6]
87
- assert len(ca) == 0
86
+ assert len(ca2) == 0
88
87
 
89
- ca = ca([1, 2, 3])
90
- assert ca.popld(42) == 1
91
- assert ca.poprd(42) == 3
92
- assert ca.popld(42) == 2
93
- assert ca.poprd(42) == 42
94
- assert ca.popld(42) == 42
95
- assert len(ca) == 0
88
+ ca3 = CA([1, 2, 3])
89
+ assert ca3.popld(42) == 1
90
+ assert ca3.poprd(42) == 3
91
+ assert ca3.popld(42) == 2
92
+ assert ca3.poprd(42) == 42
93
+ assert ca3.popld(42) == 42
94
+ assert len(ca2) == 0
96
95
  ```
97
96
 
98
97
  ______________________________________________________________________
@@ -0,0 +1,7 @@
1
+ dtools/circular_array/__init__.py,sha256=JfokAp0Jh8b5oU6aYQKNG1_8FB1OFT4geAowCLQSGQ0,1222
2
+ dtools/circular_array/ca.py,sha256=nAyi-fuIriMt2R08Ibq_KCdKuMNM199hTfye7Ap9qj8,16604
3
+ dtools/circular_array/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ dtools_circular_array-3.11.0.dist-info/licenses/LICENSE,sha256=csqbZRvA3Nyuav1aszWvswE8CZtaKr-hMjjjcKqms7w,10774
5
+ dtools_circular_array-3.11.0.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
6
+ dtools_circular_array-3.11.0.dist-info/METADATA,sha256=lE6GWKO2BQU_EEKseM5UKSLqsz5Rc-s8YdAiQt8Gjvw,3491
7
+ dtools_circular_array-3.11.0.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- dtools/circular_array/__init__.py,sha256=-GZLNI-R4UvHgg5pLNGxdNPYO8LX4Aq6eUp9rYB3Vkg,1018
2
- dtools/circular_array/ca.py,sha256=FZe0ksC9BFzQXqqRY8YXaEpF0g38CR6-rdMOWcReKcw,16534
3
- dtools/circular_array/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- dtools_circular_array-3.10.1.dist-info/licenses/LICENSE,sha256=csqbZRvA3Nyuav1aszWvswE8CZtaKr-hMjjjcKqms7w,10774
5
- dtools_circular_array-3.10.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
6
- dtools_circular_array-3.10.1.dist-info/METADATA,sha256=49FC3FiNoCuhYf7e_gf2KNlYDYZ9Gj8m4M25g2fTCjQ,3505
7
- dtools_circular_array-3.10.1.dist-info/RECORD,,