istr-python 1.1.16__tar.gz → 1.1.18__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.
- {istr_python-1.1.16 → istr_python-1.1.18}/PKG-INFO +13 -5
- {istr_python-1.1.16 → istr_python-1.1.18}/README.md +12 -4
- {istr_python-1.1.16 → istr_python-1.1.18}/istr/istr.py +72 -56
- {istr_python-1.1.16 → istr_python-1.1.18}/istr_python.egg-info/PKG-INFO +13 -5
- {istr_python-1.1.16 → istr_python-1.1.18}/pyproject.toml +1 -1
- {istr_python-1.1.16 → istr_python-1.1.18}/tests/test_istr.py +20 -4
- {istr_python-1.1.16 → istr_python-1.1.18}/istr/LICENSE.txt +0 -0
- {istr_python-1.1.16 → istr_python-1.1.18}/istr/__init__.py +0 -0
- {istr_python-1.1.16 → istr_python-1.1.18}/istr_python.egg-info/SOURCES.txt +0 -0
- {istr_python-1.1.16 → istr_python-1.1.18}/istr_python.egg-info/dependency_links.txt +0 -0
- {istr_python-1.1.16 → istr_python-1.1.18}/istr_python.egg-info/top_level.txt +0 -0
- {istr_python-1.1.16 → istr_python-1.1.18}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: istr-python
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.18
|
|
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
|
|
@@ -387,6 +387,15 @@ It is also possible to test for divisibility of an ordinary int:
|
|
|
387
387
|
istr.is_divisible(18, 3) ==> True
|
|
388
388
|
istr.is_divisible(19, 3) ==> False
|
|
389
389
|
```
|
|
390
|
+
The method `divided_by` not only tests divisibility, but also returns the result of the division. If not possible, None will be returned.
|
|
391
|
+
```
|
|
392
|
+
istr(18).divided_by(3) ==> 6 (actually istr("6"))
|
|
393
|
+
istr(18).divided_by(istr(3)) ==> 6
|
|
394
|
+
istr(19).divided_by(3) ==> None
|
|
395
|
+
istr(19).divided_by(istr(3)) ==> None
|
|
396
|
+
istr.divided_by(18, 3) ==> 6
|
|
397
|
+
istr.divided_by(19, 3) ==> None
|
|
398
|
+
```
|
|
390
399
|
#### test for square
|
|
391
400
|
|
|
392
401
|
It is possible to test whether the value is a perfect square (provided the istr can be interpreted as an int) with the `is_square` method, e.g.
|
|
@@ -693,17 +702,16 @@ Composing can also be done by prefixing a string with '=', like:
|
|
|
693
702
|
```
|
|
694
703
|
xyz = istr("=xyz")
|
|
695
704
|
print(f"{xyx=}") # ==> will print xyz=396
|
|
696
|
-
|
|
705
|
+
```
|
|
697
706
|
Note that `str(istr("="))` is "=".
|
|
698
707
|
|
|
699
708
|
Composing and assignment can be done by prefixing a string with ':=', like:
|
|
700
709
|
|
|
701
710
|
```
|
|
702
711
|
if istr(":=xyz") > 300:
|
|
703
|
-
print(f"{
|
|
704
|
-
|
|
705
|
-
Note that `str(istr(":="))` is ":=" and does not assign the value to a variable.
|
|
712
|
+
print(f"{xyz=}") # ==> will print xyz=396
|
|
706
713
|
```
|
|
714
|
+
Note that `str(istr(":="))` is ":=" and does not assign any value.
|
|
707
715
|
|
|
708
716
|
Usually, composing and decomposing uses the globals namespace, but this can be overridden with the namespace parameter. See the test suite for details.
|
|
709
717
|
|
|
@@ -374,6 +374,15 @@ It is also possible to test for divisibility of an ordinary int:
|
|
|
374
374
|
istr.is_divisible(18, 3) ==> True
|
|
375
375
|
istr.is_divisible(19, 3) ==> False
|
|
376
376
|
```
|
|
377
|
+
The method `divided_by` not only tests divisibility, but also returns the result of the division. If not possible, None will be returned.
|
|
378
|
+
```
|
|
379
|
+
istr(18).divided_by(3) ==> 6 (actually istr("6"))
|
|
380
|
+
istr(18).divided_by(istr(3)) ==> 6
|
|
381
|
+
istr(19).divided_by(3) ==> None
|
|
382
|
+
istr(19).divided_by(istr(3)) ==> None
|
|
383
|
+
istr.divided_by(18, 3) ==> 6
|
|
384
|
+
istr.divided_by(19, 3) ==> None
|
|
385
|
+
```
|
|
377
386
|
#### test for square
|
|
378
387
|
|
|
379
388
|
It is possible to test whether the value is a perfect square (provided the istr can be interpreted as an int) with the `is_square` method, e.g.
|
|
@@ -680,17 +689,16 @@ Composing can also be done by prefixing a string with '=', like:
|
|
|
680
689
|
```
|
|
681
690
|
xyz = istr("=xyz")
|
|
682
691
|
print(f"{xyx=}") # ==> will print xyz=396
|
|
683
|
-
|
|
692
|
+
```
|
|
684
693
|
Note that `str(istr("="))` is "=".
|
|
685
694
|
|
|
686
695
|
Composing and assignment can be done by prefixing a string with ':=', like:
|
|
687
696
|
|
|
688
697
|
```
|
|
689
698
|
if istr(":=xyz") > 300:
|
|
690
|
-
print(f"{
|
|
691
|
-
|
|
692
|
-
Note that `str(istr(":="))` is ":=" and does not assign the value to a variable.
|
|
699
|
+
print(f"{xyz=}") # ==> will print xyz=396
|
|
693
700
|
```
|
|
701
|
+
Note that `str(istr(":="))` is ":=" and does not assign any value.
|
|
694
702
|
|
|
695
703
|
Usually, composing and decomposing uses the globals namespace, but this can be overridden with the namespace parameter. See the test suite for details.
|
|
696
704
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# |_||___/ \__||_|
|
|
6
6
|
# strings you can count on
|
|
7
7
|
|
|
8
|
-
__version__ = "1.1.
|
|
8
|
+
__version__ = "1.1.18"
|
|
9
9
|
import functools
|
|
10
10
|
import itertools
|
|
11
11
|
import types
|
|
@@ -193,7 +193,7 @@ class istr(str):
|
|
|
193
193
|
Parameters
|
|
194
194
|
----------
|
|
195
195
|
value : any
|
|
196
|
-
if str the value will to be interpreted as an int
|
|
196
|
+
if str, the value will to be interpreted as an int
|
|
197
197
|
istr('8') ==> istr('8')
|
|
198
198
|
if numeric, the value will be interpreted as an int
|
|
199
199
|
istr(8) ==> istr('8')
|
|
@@ -296,12 +296,13 @@ class istr(str):
|
|
|
296
296
|
|
|
297
297
|
self = super().__new__(cls, as_str)
|
|
298
298
|
self._as_int = as_int
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
299
|
+
match repr_mode:
|
|
300
|
+
case "istr":
|
|
301
|
+
self._as_repr = f"{cls.__name__}({repr(as_str)})"
|
|
302
|
+
case "int":
|
|
303
|
+
self._as_repr = "?" if as_int is self._nan else repr(as_int)
|
|
304
|
+
case _:
|
|
305
|
+
self._as_repr = repr(as_str)
|
|
305
306
|
self._this_base = base
|
|
306
307
|
self._this_int_format = int_format
|
|
307
308
|
self._this_repr_mode = repr_mode
|
|
@@ -397,38 +398,45 @@ class istr(str):
|
|
|
397
398
|
return not istr.is_divisible_by(self, 2)
|
|
398
399
|
|
|
399
400
|
def is_divisible_by(self, divisor):
|
|
400
|
-
return
|
|
401
|
+
return istr.divided_by(self, divisor) is not None
|
|
402
|
+
|
|
403
|
+
def divided_by(self, divisor):
|
|
404
|
+
if divisor == 0:
|
|
405
|
+
return None
|
|
406
|
+
quotient, remainder = divmod(istr.interpret_as_int(self), int(divisor))
|
|
407
|
+
return istr(quotient) if remainder == 0 else None
|
|
401
408
|
|
|
402
409
|
def is_square(self):
|
|
403
|
-
|
|
404
|
-
if n < 1000000:
|
|
405
|
-
return n in _squares_up_to_1_000_000()
|
|
406
|
-
return n == round(n ** (1 / 2)) ** 2
|
|
410
|
+
return istr.is_power_of(self, 2)
|
|
407
411
|
|
|
408
412
|
def is_cube(self):
|
|
409
|
-
|
|
410
|
-
if n < 1000000:
|
|
411
|
-
return n in _cubes_up_to_1_000_000()
|
|
412
|
-
return n == round(n ** (1 / 3)) ** 3
|
|
413
|
+
return istr.is_power_of(self, 3)
|
|
413
414
|
|
|
414
415
|
def is_power_of(self, exponent):
|
|
415
416
|
n = istr.interpret_as_int(self)
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
417
|
+
match exponent:
|
|
418
|
+
case 2:
|
|
419
|
+
if n < 1000000:
|
|
420
|
+
return n in _squares_up_to_1_000_000()
|
|
421
|
+
case 3:
|
|
422
|
+
if n < 1000000:
|
|
423
|
+
return n in _cubes_up_to_1_000_000()
|
|
424
|
+
case 0:
|
|
425
|
+
return n == 1
|
|
426
|
+
case _ if exponent < 0:
|
|
427
|
+
raise ValueError(f"exponent must be >=1; not {exponent}")
|
|
428
|
+
case _ if not isinstance(exponent, int):
|
|
429
|
+
raise TypeError(f"exponent must be int; not {type(exponent)}")
|
|
420
430
|
return n >= 0 and n == round(n ** (1 / exponent)) ** exponent
|
|
421
431
|
|
|
422
432
|
def is_prime(self):
|
|
423
433
|
n = istr.interpret_as_int(self)
|
|
424
|
-
if n < 2:
|
|
425
|
-
return False
|
|
426
|
-
if n == 2:
|
|
427
|
-
return True
|
|
428
|
-
if not n & 1:
|
|
429
|
-
return False
|
|
430
434
|
if n < 1000000:
|
|
431
435
|
return n in _primes_up_to_1_000_000()
|
|
436
|
+
|
|
437
|
+
if not n & 1:
|
|
438
|
+
return False
|
|
439
|
+
|
|
432
440
|
for x in range(3, int(n**0.5) + 1, 2):
|
|
433
441
|
if n % x == 0:
|
|
434
442
|
return False
|
|
@@ -441,35 +449,33 @@ class istr(str):
|
|
|
441
449
|
"""
|
|
442
450
|
if ("primes", lb_or_ub, ub) in _cache:
|
|
443
451
|
return _cache["primes", lb_or_ub, ub]
|
|
444
|
-
result =
|
|
452
|
+
result = list(map(cls, _primes(lb_or_ub, ub)))
|
|
445
453
|
if cache:
|
|
446
|
-
_cache["primes", lb_or_ub, ub]=result
|
|
447
|
-
return result
|
|
454
|
+
_cache["primes", lb_or_ub, ub] = result
|
|
455
|
+
return result
|
|
448
456
|
|
|
449
457
|
@classmethod
|
|
450
458
|
def squares(cls, lb_or_ub, ub=None, cache=True):
|
|
451
459
|
"""
|
|
452
460
|
returns all squares up to a given upperbound or between a given lowerbound and upperbound
|
|
453
461
|
"""
|
|
454
|
-
return istr.power_ofs(2,lb_or_ub, ub, cache=cache)
|
|
462
|
+
return istr.power_ofs(2, lb_or_ub, ub, cache=cache)
|
|
455
463
|
|
|
456
464
|
@classmethod
|
|
457
465
|
def cubes(cls, lb_or_ub, ub=None, cache=True):
|
|
458
|
-
return istr.power_ofs(3,lb_or_ub, ub, cache=cache)
|
|
466
|
+
return istr.power_ofs(3, lb_or_ub, ub, cache=cache)
|
|
459
467
|
|
|
460
468
|
@classmethod
|
|
461
|
-
def power_ofs(cls, n,lb_or_ub, ub=None, cache=True):
|
|
469
|
+
def power_ofs(cls, n, lb_or_ub, ub=None, cache=True):
|
|
462
470
|
"""
|
|
463
471
|
returns all power of n up to a given upperbound or between a given lowerbound and upperbound
|
|
464
472
|
"""
|
|
465
473
|
if ("power_ofs", n, lb_or_ub, ub) in _cache:
|
|
466
474
|
return _cache["power_ofs", n, lb_or_ub, ub]
|
|
467
|
-
result =
|
|
475
|
+
result = list(map(cls, _power_ofs(n, lb_or_ub, ub)))
|
|
468
476
|
if cache:
|
|
469
|
-
_cache["power_ofs", n, lb_or_ub, ub]=result
|
|
470
|
-
return result
|
|
471
|
-
|
|
472
|
-
|
|
477
|
+
_cache["power_ofs", n, lb_or_ub, ub] = result
|
|
478
|
+
return result
|
|
473
479
|
|
|
474
480
|
def decompose(self, letters, namespace=None):
|
|
475
481
|
"""
|
|
@@ -796,52 +802,62 @@ def _map(func, *iterables, strict=False):
|
|
|
796
802
|
|
|
797
803
|
yield func(*values)
|
|
798
804
|
|
|
799
|
-
|
|
805
|
+
|
|
806
|
+
_cache = {}
|
|
807
|
+
|
|
800
808
|
|
|
801
809
|
def _primes(lb_or_ub, ub=None):
|
|
802
810
|
lb, ub = (0, lb_or_ub) if ub is None else (lb_or_ub, ub)
|
|
811
|
+
if lb < 0:
|
|
812
|
+
lb = 0
|
|
803
813
|
sieve = bytearray(b"\x01") * (ub + 1)
|
|
804
814
|
sieve[0:2] = b"\x00\x00"
|
|
805
815
|
|
|
806
|
-
for i in range(2, int(ub**0.5)+1
|
|
816
|
+
for i in range(2, int(ub**0.5) + 1):
|
|
807
817
|
if sieve[i]:
|
|
808
818
|
sieve[i * i : ub + 1 : i] = b"\x00" * (((ub - i * i) // i) + 1)
|
|
809
819
|
|
|
810
|
-
return
|
|
820
|
+
return [i for i, is_prime in enumerate(sieve) if is_prime and lb <= i < ub]
|
|
811
821
|
|
|
812
822
|
|
|
813
823
|
@functools.lru_cache(maxsize=1)
|
|
814
824
|
def _primes_up_to_1_000_000():
|
|
815
|
-
return _primes(1000000)
|
|
825
|
+
return set(_primes(1000000))
|
|
816
826
|
|
|
817
827
|
|
|
818
828
|
@functools.lru_cache(maxsize=1)
|
|
819
829
|
def _squares_up_to_1_000_000():
|
|
820
|
-
return _power_ofs(2,1000000)
|
|
830
|
+
return set(_power_ofs(2, 1000000))
|
|
831
|
+
|
|
821
832
|
|
|
822
833
|
@functools.lru_cache(maxsize=1)
|
|
823
834
|
def _cubes_up_to_1_000_000():
|
|
824
|
-
return _power_ofs(3,1000000)
|
|
835
|
+
return set(_power_ofs(3, 1000000))
|
|
825
836
|
|
|
826
837
|
|
|
827
838
|
def _power_ofs(n, lb_or_ub, ub=None):
|
|
828
839
|
lb, ub = (0, lb_or_ub) if ub is None else (lb_or_ub, ub)
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
i
|
|
840
|
+
if lb < 0:
|
|
841
|
+
lb = 0
|
|
842
|
+
result = []
|
|
843
|
+
match n:
|
|
844
|
+
case 0:
|
|
845
|
+
if lb <= 1 < ub:
|
|
846
|
+
result.append(1)
|
|
847
|
+
case 1:
|
|
848
|
+
result = {*range(lb, ub)}
|
|
849
|
+
case _:
|
|
850
|
+
i = int(lb ** (1 / n))
|
|
851
|
+
while (i_n := i**n) < ub:
|
|
852
|
+
if i_n >= lb:
|
|
853
|
+
result.append(i_n)
|
|
854
|
+
i += 1
|
|
841
855
|
return result
|
|
842
856
|
|
|
857
|
+
|
|
843
858
|
istr.type = type(istr(0))
|
|
844
859
|
|
|
860
|
+
|
|
845
861
|
class istrModule(types.ModuleType):
|
|
846
862
|
def __call__(self, *args, **kwargs):
|
|
847
863
|
return istr(*args, **kwargs)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: istr-python
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.18
|
|
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
|
|
@@ -387,6 +387,15 @@ It is also possible to test for divisibility of an ordinary int:
|
|
|
387
387
|
istr.is_divisible(18, 3) ==> True
|
|
388
388
|
istr.is_divisible(19, 3) ==> False
|
|
389
389
|
```
|
|
390
|
+
The method `divided_by` not only tests divisibility, but also returns the result of the division. If not possible, None will be returned.
|
|
391
|
+
```
|
|
392
|
+
istr(18).divided_by(3) ==> 6 (actually istr("6"))
|
|
393
|
+
istr(18).divided_by(istr(3)) ==> 6
|
|
394
|
+
istr(19).divided_by(3) ==> None
|
|
395
|
+
istr(19).divided_by(istr(3)) ==> None
|
|
396
|
+
istr.divided_by(18, 3) ==> 6
|
|
397
|
+
istr.divided_by(19, 3) ==> None
|
|
398
|
+
```
|
|
390
399
|
#### test for square
|
|
391
400
|
|
|
392
401
|
It is possible to test whether the value is a perfect square (provided the istr can be interpreted as an int) with the `is_square` method, e.g.
|
|
@@ -693,17 +702,16 @@ Composing can also be done by prefixing a string with '=', like:
|
|
|
693
702
|
```
|
|
694
703
|
xyz = istr("=xyz")
|
|
695
704
|
print(f"{xyx=}") # ==> will print xyz=396
|
|
696
|
-
|
|
705
|
+
```
|
|
697
706
|
Note that `str(istr("="))` is "=".
|
|
698
707
|
|
|
699
708
|
Composing and assignment can be done by prefixing a string with ':=', like:
|
|
700
709
|
|
|
701
710
|
```
|
|
702
711
|
if istr(":=xyz") > 300:
|
|
703
|
-
print(f"{
|
|
704
|
-
|
|
705
|
-
Note that `str(istr(":="))` is ":=" and does not assign the value to a variable.
|
|
712
|
+
print(f"{xyz=}") # ==> will print xyz=396
|
|
706
713
|
```
|
|
714
|
+
Note that `str(istr(":="))` is ":=" and does not assign any value.
|
|
707
715
|
|
|
708
716
|
Usually, composing and decomposing uses the globals namespace, but this can be overridden with the namespace parameter. See the test suite for details.
|
|
709
717
|
|
|
@@ -343,6 +343,17 @@ def test_is_divisible_by():
|
|
|
343
343
|
assert not istr.is_divisible_by(19, 3)
|
|
344
344
|
|
|
345
345
|
|
|
346
|
+
def test_divided_by():
|
|
347
|
+
assert istr(18).divided_by(3).equals(istr(6))
|
|
348
|
+
assert istr(18).divided_by(istr(3)).equals(istr(6))
|
|
349
|
+
assert istr(19).divided_by(3) is None
|
|
350
|
+
assert istr(19).divided_by(istr(3)) is None
|
|
351
|
+
with pytest.raises(TypeError, match=re.escape(f"not interpretable as int")):
|
|
352
|
+
istr("a").divided_by(3)
|
|
353
|
+
assert istr.divided_by(18, 3).equals(istr(6))
|
|
354
|
+
assert istr.divided_by(19, 3) is None
|
|
355
|
+
|
|
356
|
+
|
|
346
357
|
def test_is_square():
|
|
347
358
|
assert not istr(-1).is_square()
|
|
348
359
|
assert istr(0).is_square()
|
|
@@ -441,11 +452,16 @@ def test_cubes():
|
|
|
441
452
|
assert istr.cubes(27, 50) == [istr("27")]
|
|
442
453
|
assert id(istr.cubes(100)) == id(istr.cubes(100)) # test caching
|
|
443
454
|
|
|
455
|
+
|
|
444
456
|
def test_power_ofs():
|
|
445
|
-
assert istr.power_ofs(
|
|
446
|
-
assert istr.power_ofs(
|
|
447
|
-
assert
|
|
448
|
-
assert
|
|
457
|
+
assert istr.power_ofs(0, 1, 5) == [istr("1")]
|
|
458
|
+
assert istr.power_ofs(0, 1) == []
|
|
459
|
+
assert istr.power_ofs(1, -1, 5) == [istr("0"), istr("1"), istr("2"), istr("3"), istr("4")]
|
|
460
|
+
assert istr.power_ofs(1, 0) == []
|
|
461
|
+
assert istr.power_ofs(3, 1, 50) == [istr("1"), istr("8"), istr("27")]
|
|
462
|
+
assert istr.power_ofs(5, 1, 500) == [istr("1"), istr("32"), istr("243")]
|
|
463
|
+
assert id(istr.power_ofs(3, 2000)) != id(istr.cubes(3, 2000)) # test caching
|
|
464
|
+
assert id(istr.power_ofs(3, 1000, cache=False)) != id(istr.cubes(3, 1000, cache=False)) # test caching
|
|
449
465
|
|
|
450
466
|
|
|
451
467
|
def test_join():
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|