istr-python 1.1.7__tar.gz → 1.1.8.post0__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: istr-python
3
- Version: 1.1.7
3
+ Version: 1.1.8.post0
4
4
  Summary: istr - strings you can count on
5
5
  Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/salabim/istr
@@ -8,7 +8,7 @@ Project-URL: Repository, https://github.com/salabim/istr
8
8
  Classifier: Development Status :: 5 - Production/Stable
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3 :: Only
11
- Requires-Python: >=3.7
11
+ Requires-Python: >=3.8
12
12
  Description-Content-Type: text/markdown
13
13
 
14
14
  <img src="https://www.salabim.org/istr/istr_logo.png" width=500>
@@ -556,6 +556,25 @@ list(istr.concat(istr.permutations(range(3),2))) ==>
556
556
  [istr('01'), istr('02'), istr('10'), istr('12'), istr('20'), istr('21')]
557
557
  ```
558
558
 
559
+ #### prod to get product of an iterable
560
+
561
+ The method `prod` can be used to return the product of an iterable (including an istr), like `math.prod`, but as istr.
562
+ Thus, `istr.prod(range(1,5))` is `istr(24)`
563
+ And `istr("123", start=4)` is also `istr(24)`.
564
+
565
+ It is also possible to apply `prod` on an istr:
566
+ `istr(1234).prod()` is `istr(24)`
567
+ `istr("123").prod(start=4)` is `istr(24)`
568
+
569
+ #### sumprod to get the sum of products of iterables
570
+
571
+ The class method `istr.sumprod()`, is equivalent to `math.sumprod()`, but applies istr to both iterables.
572
+ Note that this method is available even in Python < 3.12 .
573
+ Thus, `istr.sumprod("12", (3,4))` is `istr(11)`
574
+ In contrast with `math.sumprod()`, `istr.sumprod()` supports a `strict` parameter (True by default)
575
+ Thus, `istr.sumprod("12", (3,4,5), strict=False)` is `istr(11)`, whereas `istr.sumprod("12", (3,4,5))`
576
+ raises a ValueError.
577
+
559
578
  #### generate istr with digits
560
579
 
561
580
  The class method `digits` can be used to return an istr of digits according to a given specification.
@@ -543,6 +543,25 @@ list(istr.concat(istr.permutations(range(3),2))) ==>
543
543
  [istr('01'), istr('02'), istr('10'), istr('12'), istr('20'), istr('21')]
544
544
  ```
545
545
 
546
+ #### prod to get product of an iterable
547
+
548
+ The method `prod` can be used to return the product of an iterable (including an istr), like `math.prod`, but as istr.
549
+ Thus, `istr.prod(range(1,5))` is `istr(24)`
550
+ And `istr("123", start=4)` is also `istr(24)`.
551
+
552
+ It is also possible to apply `prod` on an istr:
553
+ `istr(1234).prod()` is `istr(24)`
554
+ `istr("123").prod(start=4)` is `istr(24)`
555
+
556
+ #### sumprod to get the sum of products of iterables
557
+
558
+ The class method `istr.sumprod()`, is equivalent to `math.sumprod()`, but applies istr to both iterables.
559
+ Note that this method is available even in Python < 3.12 .
560
+ Thus, `istr.sumprod("12", (3,4))` is `istr(11)`
561
+ In contrast with `math.sumprod()`, `istr.sumprod()` supports a `strict` parameter (True by default)
562
+ Thus, `istr.sumprod("12", (3,4,5), strict=False)` is `istr(11)`, whereas `istr.sumprod("12", (3,4,5))`
563
+ raises a ValueError.
564
+
546
565
  #### generate istr with digits
547
566
 
548
567
  The class method `digits` can be used to return an istr of digits according to a given specification.
@@ -5,12 +5,14 @@
5
5
  # |_||___/ \__||_|
6
6
  # strings you can count on
7
7
 
8
- __version__ = "1.1.7"
8
+ __version__ = "1.1.8"
9
9
  import functools
10
10
  import itertools
11
11
  import types
12
12
  import sys
13
13
  import inspect
14
+ import math
15
+ import operator
14
16
 
15
17
  """
16
18
  Note: the changelog is now in changelog.md
@@ -230,7 +232,7 @@ class istr(str):
230
232
  return int(value, cls._base)
231
233
  else:
232
234
  return int(value)
233
- except:
235
+ except Exception:
234
236
  return cls._nan
235
237
 
236
238
  def __new__(cls, *value):
@@ -251,8 +253,8 @@ class istr(str):
251
253
  return map(functools.partial(cls), value)
252
254
  return type(value)(map(functools.partial(cls), value))
253
255
 
254
- if isinstance(value, str) and value.startswith('='):
255
- value=str(cls.compose(value[1:],inspect.currentframe().f_back.f_back.f_globals))
256
+ if isinstance(value, str) and value.startswith("="):
257
+ value = str(cls.compose(value[1:], inspect.currentframe().f_back.f_back.f_globals))
256
258
  as_int = cls._to_int(value)
257
259
  if isinstance(value, str):
258
260
  as_str = value
@@ -349,10 +351,10 @@ class istr(str):
349
351
  return int(self._as_int)
350
352
 
351
353
  def is_even(self):
352
- return istr.is_divisible_by(self,2)
354
+ return istr.is_divisible_by(self, 2)
353
355
 
354
356
  def is_odd(self):
355
- return not istr.is_divisible_by(self,2)
357
+ return not istr.is_divisible_by(self, 2)
356
358
 
357
359
  def is_divisible_by(self, divisor):
358
360
  return istr.interpret_as_int(self) % int(divisor) == 0
@@ -489,6 +491,17 @@ class istr(str):
489
491
  def concat(cls, iterable):
490
492
  return map(lambda x: istr("").join(x), istr(iterable))
491
493
 
494
+
495
+ def prod(self, *, start=1):
496
+ return math.prod(self, start=istr(start))
497
+
498
+
499
+ @classmethod
500
+ def sumprod(cls, p, q, /, strict=True):
501
+ if "sumprod" in math.__dict__ and strict:
502
+ return istr(math.sumprod(p, q))
503
+ return sum(_map(operator.__mul__, cls(p), cls(q), strict=strict))
504
+
492
505
  @classmethod
493
506
  def enumerate(cls, iterable, start=0):
494
507
  for i, value in enumerate(iterable, start):
@@ -519,7 +532,7 @@ class istr(str):
519
532
  def __new__(cls, cls_repr_mode, mode=None):
520
533
  if mode is None:
521
534
  return cls_repr_mode._repr_mode
522
- if mode == int:
535
+ if mode is int:
523
536
  mode = "int"
524
537
  if mode in ("istr", "str", "int"): # _istr is used only for TypeErrors
525
538
  return super().__new__(cls)
@@ -628,6 +641,41 @@ class istr(str):
628
641
  return result
629
642
 
630
643
 
644
+ def _map(func, *iterables, strict=False):
645
+ """
646
+ like map, but with a strict parameter (also for Python < 3.14)
647
+ """
648
+ if sys.version_info >= (3, 14):
649
+ yield from map(func, *iterables, strict=strict)
650
+ return
651
+
652
+ if not strict:
653
+ yield from map(func, *iterables)
654
+ return
655
+
656
+ iterators = [iter(it) for it in iterables]
657
+
658
+ while True:
659
+ values = []
660
+ exhausted = []
661
+ for it in iterators:
662
+ try:
663
+ v = next(it)
664
+ values.append(v)
665
+ exhausted.append(False)
666
+ except StopIteration:
667
+ values.append(None)
668
+ exhausted.append(True)
669
+
670
+ if all(exhausted):
671
+ return
672
+
673
+ if any(exhausted) and not all(exhausted):
674
+ raise ValueError("map_strict: iterables have different lengths")
675
+
676
+ yield func(*values)
677
+
678
+
631
679
  istr.type = type(istr(0))
632
680
 
633
681
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: istr-python
3
- Version: 1.1.7
3
+ Version: 1.1.8.post0
4
4
  Summary: istr - strings you can count on
5
5
  Author-email: Ruud van der Ham <rt.van.der.ham@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/salabim/istr
@@ -8,7 +8,7 @@ Project-URL: Repository, https://github.com/salabim/istr
8
8
  Classifier: Development Status :: 5 - Production/Stable
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Programming Language :: Python :: 3 :: Only
11
- Requires-Python: >=3.7
11
+ Requires-Python: >=3.8
12
12
  Description-Content-Type: text/markdown
13
13
 
14
14
  <img src="https://www.salabim.org/istr/istr_logo.png" width=500>
@@ -556,6 +556,25 @@ list(istr.concat(istr.permutations(range(3),2))) ==>
556
556
  [istr('01'), istr('02'), istr('10'), istr('12'), istr('20'), istr('21')]
557
557
  ```
558
558
 
559
+ #### prod to get product of an iterable
560
+
561
+ The method `prod` can be used to return the product of an iterable (including an istr), like `math.prod`, but as istr.
562
+ Thus, `istr.prod(range(1,5))` is `istr(24)`
563
+ And `istr("123", start=4)` is also `istr(24)`.
564
+
565
+ It is also possible to apply `prod` on an istr:
566
+ `istr(1234).prod()` is `istr(24)`
567
+ `istr("123").prod(start=4)` is `istr(24)`
568
+
569
+ #### sumprod to get the sum of products of iterables
570
+
571
+ The class method `istr.sumprod()`, is equivalent to `math.sumprod()`, but applies istr to both iterables.
572
+ Note that this method is available even in Python < 3.12 .
573
+ Thus, `istr.sumprod("12", (3,4))` is `istr(11)`
574
+ In contrast with `math.sumprod()`, `istr.sumprod()` supports a `strict` parameter (True by default)
575
+ Thus, `istr.sumprod("12", (3,4,5), strict=False)` is `istr(11)`, whereas `istr.sumprod("12", (3,4,5))`
576
+ raises a ValueError.
577
+
559
578
  #### generate istr with digits
560
579
 
561
580
  The class method `digits` can be used to return an istr of digits according to a given specification.
@@ -10,9 +10,9 @@ authors = [
10
10
  { name = "Ruud van der Ham", email = "rt.van.der.ham@gmail.com" },
11
11
  ]
12
12
  description = "istr - strings you can count on"
13
- version = "1.1.7"
13
+ version = "1.1.8.post0"
14
14
  readme = "README.md"
15
- requires-python = ">=3.7"
15
+ requires-python = ">=3.8"
16
16
  dependencies = []
17
17
  classifiers = [
18
18
  "Development Status :: 5 - Production/Stable",
@@ -313,7 +313,8 @@ def test_even_odd():
313
313
  assert istr.is_even(12345678)
314
314
  assert istr.is_odd(11111111)
315
315
 
316
- def test_is_divisible():
316
+
317
+ def test_is_divisible_by():
317
318
  assert istr(18).is_divisible_by(3)
318
319
  assert istr(18).is_divisible_by(istr(3))
319
320
  assert not istr(19).is_divisible_by(3)
@@ -323,6 +324,7 @@ def test_is_divisible():
323
324
  assert istr.is_divisible_by(18, 3)
324
325
  assert not istr.is_divisible_by(19, 3)
325
326
 
327
+
326
328
  def test_is_square():
327
329
  assert not istr(-1).is_square()
328
330
  assert istr(0).is_square()
@@ -339,6 +341,7 @@ def test_is_square():
339
341
  assert istr.is_square(4)
340
342
  assert istr.is_square(16)
341
343
 
344
+
342
345
  def test_is_cube():
343
346
  assert not istr(-1).is_cube()
344
347
  assert istr(0).is_cube()
@@ -366,16 +369,17 @@ def test_is_power_of():
366
369
  assert not istr(99).is_power_of(3)
367
370
  with pytest.raises(TypeError, match=re.escape(f"not interpretable as int")):
368
371
  istr("a").is_power_of(3)
369
- assert istr.is_power_of(0,3)
370
- assert istr.is_power_of(1,3)
371
- assert not istr.is_power_of(2,3)
372
- assert istr.is_power_of(8,3)
373
- assert istr.is_power_of(27,3)
372
+ assert istr.is_power_of(0, 3)
373
+ assert istr.is_power_of(1, 3)
374
+ assert not istr.is_power_of(2, 3)
375
+ assert istr.is_power_of(8, 3)
376
+ assert istr.is_power_of(27, 3)
374
377
  with pytest.raises(TypeError):
375
378
  istr(1).is_power_of(3.1)
376
379
  with pytest.raises(ValueError):
377
380
  istr(1).is_power_of(-1)
378
-
381
+
382
+
379
383
  def test_is_prime():
380
384
  assert not istr(0).is_prime()
381
385
  assert not istr(1).is_prime()
@@ -553,12 +557,13 @@ def test_unpacking():
553
557
  assert x.equals(istr(1))
554
558
  assert y.equals(istr(2))
555
559
  assert z.equals(istr(3))
556
- del x,y,z
560
+ del x, y, z
557
561
 
558
562
  x, y, z = a
559
563
  assert x.equals(istr(1))
560
564
  assert y.equals(istr(2))
561
- assert z=="3"
565
+ assert z == "3"
566
+
562
567
 
563
568
  def test_repr_mode():
564
569
  hundred = istr(100)
@@ -649,9 +654,6 @@ def test_base():
649
654
  assert a * a == 225
650
655
 
651
656
 
652
-
653
-
654
-
655
657
  def test_digits():
656
658
  assert istr.digits().equals(istr("0123456789"))
657
659
  assert istr.digits("").equals(istr("0123456789"))
@@ -703,13 +705,16 @@ def test_itertools():
703
705
  assert list(istr.dropwhile(lambda x: x < 5, [1, 4, 6, 4, 1])) == [istr("6"), istr("4"), istr("1")]
704
706
  assert list(istr.filterfalse(lambda x: x % 2, range(10))) == [istr("0"), istr("2"), istr("4"), istr("6"), istr("8")]
705
707
  assert list(istr.islice("123456", 2)) == [istr("1"), istr("2")]
706
- assert list(istr.pairwise("1234")) == [(istr("1"), istr("2")), (istr("2"), istr("3")), (istr("3"), istr("4"))]
707
708
  assert list(istr.permutations(range(5), 3)) == list(istr(itertools.permutations(range(5), 3)))
708
709
  assert list(istr.product(range(5), range(4))) == list(istr(itertools.product(range(5), range(4))))
709
710
  assert list100(istr.repeat(10)) == list100(istr(itertools.repeat(10)))
710
711
  assert list(istr.starmap(pow, [(2, 5), (3, 2), (10, 3)])) == [istr("32"), istr("9"), istr("1000")]
711
712
  assert list(istr.takewhile(lambda x: x < 5, [1, 4, 6, 3, 8])) == [istr("1"), istr("4")]
712
713
  assert list(istr.zip_longest("123", "56", fillvalue="0")) == [(istr("1"), istr("5")), (istr("2"), istr("6")), (istr("3"), istr("0"))]
714
+ if sys.version_info >= (3, 10):
715
+ assert list(istr.pairwise("1234")) == [(istr("1"), istr("2")), (istr("2"), istr("3")), (istr("3"), istr("4"))]
716
+ if sys.version_info >= (3, 12):
717
+ assert list(istr.batched("12345", n=2)) == [(istr("1"), istr("2")), (istr("3"), istr("4")), (istr("5"),)]
713
718
 
714
719
 
715
720
  def test_all_distinct():
@@ -718,6 +723,25 @@ def test_all_distinct():
718
723
  assert istr("").all_distinct()
719
724
 
720
725
 
726
+ def test_prod():
727
+ assert istr.prod(range(1, 5)).equals(istr(24))
728
+ assert istr.prod((1, 2, 3), start=4).equals(istr(24))
729
+ assert istr("1234").prod().equals(istr(24))
730
+ assert istr("123").prod(start=4).equals(istr(24))
731
+
732
+
733
+ def test_sumprod():
734
+ assert istr.sumprod((1, 2), (3, 4)).equals(istr(11))
735
+ assert istr.sumprod(istr("12"), (3, 4)).equals(istr(11))
736
+ assert istr.sumprod(istr("12"), "34").equals(istr(11))
737
+ assert istr.sumprod(istr("12"), "34", strict=False).equals(istr(11))
738
+ assert istr.sumprod(istr("12"), "345", strict=False).equals(istr(11))
739
+ with pytest.raises(ValueError):
740
+ istr.sumprod((1, 2), (3, 4, 5))
741
+ with pytest.raises(ValueError):
742
+ istr.sumprod((1, 2), (3, 4, 5), strict=True)
743
+
744
+
721
745
  def test_subclassing():
722
746
  class jstr(istr.type): ...
723
747
 
@@ -750,8 +774,6 @@ def test_decompose():
750
774
  istr(12).decompose("xyz")
751
775
  with pytest.raises(ValueError):
752
776
  istr(123).decompose("xy1")
753
-
754
-
755
777
 
756
778
 
757
779
  def test_compose():
File without changes