istr-python 1.1.24__tar.gz → 1.1.26__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.24 → istr_python-1.1.26}/PKG-INFO +17 -1
- {istr_python-1.1.24 → istr_python-1.1.26}/README.md +16 -0
- {istr_python-1.1.24 → istr_python-1.1.26}/istr/istr.py +41 -30
- {istr_python-1.1.24 → istr_python-1.1.26}/istr_python.egg-info/PKG-INFO +17 -1
- {istr_python-1.1.24 → istr_python-1.1.26}/pyproject.toml +1 -1
- {istr_python-1.1.24 → istr_python-1.1.26}/tests/test_istr.py +14 -3
- {istr_python-1.1.24 → istr_python-1.1.26}/istr/LICENSE.txt +0 -0
- {istr_python-1.1.24 → istr_python-1.1.26}/istr/__init__.py +0 -0
- {istr_python-1.1.24 → istr_python-1.1.26}/istr_python.egg-info/SOURCES.txt +0 -0
- {istr_python-1.1.24 → istr_python-1.1.26}/istr_python.egg-info/dependency_links.txt +0 -0
- {istr_python-1.1.24 → istr_python-1.1.26}/istr_python.egg-info/top_level.txt +0 -0
- {istr_python-1.1.24 → istr_python-1.1.26}/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.26
|
|
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
|
|
@@ -379,6 +379,22 @@ It is also possible to test for even/odd of an ordinary int:
|
|
|
379
379
|
istr.is_even(4) ==> True
|
|
380
380
|
istr.is_odd(5) ==> True
|
|
381
381
|
```
|
|
382
|
+
|
|
383
|
+
#### test for palindrome
|
|
384
|
+
|
|
385
|
+
It is possible to test whether an istr is palindromic, like
|
|
386
|
+
```
|
|
387
|
+
istr(12321).is_palindrome() ==> True
|
|
388
|
+
istr('aba').is_palindrome() ==> True
|
|
389
|
+
istr(123).is_palindrome() ==> False
|
|
390
|
+
```
|
|
391
|
+
It is also possible to test for a palindrome for anything that can be converted to a str:
|
|
392
|
+
```
|
|
393
|
+
istr.is_palindrome(121) ==> True
|
|
394
|
+
istr.is_palindrome('no devil lived on') ==> True
|
|
395
|
+
istr.is_palindrome(min) ==> False
|
|
396
|
+
```
|
|
397
|
+
|
|
382
398
|
#### test for divisibility
|
|
383
399
|
|
|
384
400
|
It is possible to test whether an istr is divisible by a given value with the `is_divisible_by method,` e.g.
|
|
@@ -366,6 +366,22 @@ It is also possible to test for even/odd of an ordinary int:
|
|
|
366
366
|
istr.is_even(4) ==> True
|
|
367
367
|
istr.is_odd(5) ==> True
|
|
368
368
|
```
|
|
369
|
+
|
|
370
|
+
#### test for palindrome
|
|
371
|
+
|
|
372
|
+
It is possible to test whether an istr is palindromic, like
|
|
373
|
+
```
|
|
374
|
+
istr(12321).is_palindrome() ==> True
|
|
375
|
+
istr('aba').is_palindrome() ==> True
|
|
376
|
+
istr(123).is_palindrome() ==> False
|
|
377
|
+
```
|
|
378
|
+
It is also possible to test for a palindrome for anything that can be converted to a str:
|
|
379
|
+
```
|
|
380
|
+
istr.is_palindrome(121) ==> True
|
|
381
|
+
istr.is_palindrome('no devil lived on') ==> True
|
|
382
|
+
istr.is_palindrome(min) ==> False
|
|
383
|
+
```
|
|
384
|
+
|
|
369
385
|
#### test for divisibility
|
|
370
386
|
|
|
371
387
|
It is possible to test whether an istr is divisible by a given value with the `is_divisible_by method,` e.g.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
# |_||___/ \__||_|
|
|
6
6
|
# strings you can count on
|
|
7
7
|
|
|
8
|
-
__version__ = "1.1.
|
|
8
|
+
__version__ = "1.1.26"
|
|
9
9
|
import functools
|
|
10
10
|
import itertools
|
|
11
11
|
import types
|
|
@@ -17,7 +17,7 @@ import copy
|
|
|
17
17
|
import bisect
|
|
18
18
|
|
|
19
19
|
"""
|
|
20
|
-
Note: the changelog is
|
|
20
|
+
Note: the changelog is in changelog.md
|
|
21
21
|
|
|
22
22
|
You can view the changelog on www.salabim.org/istr/changelog
|
|
23
23
|
|
|
@@ -198,6 +198,10 @@ class istr(str):
|
|
|
198
198
|
istr('8') ==> istr('8')
|
|
199
199
|
if numeric, the value will be interpreted as an int
|
|
200
200
|
istr(8) ==> istr('8')
|
|
201
|
+
if str and starts with '=', the value will be retrieved from letter variables and other characters unprocessed, e.g.
|
|
202
|
+
if a=4 and b=32, istr('=ab1') will be istr'('4321')
|
|
203
|
+
if str and starts with ':=', the value will be retrieved from letter variables. And the corresponding value will be set, e.g.
|
|
204
|
+
if a=4 and b=32, istr(':=ab') will be istr'('432') and ab will be assigned that value too.
|
|
201
205
|
if a dict (or subtype of dict), the same type dict will be returned with all values istr'ed
|
|
202
206
|
istr({0: 0, 1: 1, 2: 4}) ==> {0: istr('0'), 1: istr('1'), 2: istr('4')}
|
|
203
207
|
if an iterator, the iterator will be mapped with istr
|
|
@@ -281,9 +285,9 @@ class istr(str):
|
|
|
281
285
|
value = str(cls.compose(value[1:], namespace=get_namespace(namespace)))
|
|
282
286
|
else: # it's :=
|
|
283
287
|
var_name = value[2:]
|
|
284
|
-
value = str(cls.compose(value[2:], namespace=get_namespace(namespace)))
|
|
285
288
|
if not var_name.isidentifier():
|
|
286
289
|
raise ValueError(f"{var_name!r} is not a valid identifier")
|
|
290
|
+
value = str(cls.compose(var_name, namespace=get_namespace(namespace)))
|
|
287
291
|
get_namespace(namespace)[var_name] = cls(value)
|
|
288
292
|
as_int = cls._to_int(value, base)
|
|
289
293
|
if as_int is cls._nan or isinstance(value, str):
|
|
@@ -311,7 +315,7 @@ class istr(str):
|
|
|
311
315
|
return hash((self.__class__, str(self)))
|
|
312
316
|
|
|
313
317
|
def __eq__(self, other):
|
|
314
|
-
if isinstance(other,
|
|
318
|
+
if isinstance(other, istr):
|
|
315
319
|
if self.is_int() and other.is_int():
|
|
316
320
|
return self._as_int == other._as_int
|
|
317
321
|
if isinstance(other, str):
|
|
@@ -398,6 +402,9 @@ class istr(str):
|
|
|
398
402
|
|
|
399
403
|
def is_odd(self):
|
|
400
404
|
return not istr.is_divisible_by(self, 2)
|
|
405
|
+
|
|
406
|
+
def is_palindrome(self):
|
|
407
|
+
return str(self)==str(self)[::-1]
|
|
401
408
|
|
|
402
409
|
def is_divisible_by(self, divisor):
|
|
403
410
|
return istr.divided_by(self, divisor) is not None
|
|
@@ -410,7 +417,7 @@ class istr(str):
|
|
|
410
417
|
|
|
411
418
|
def is_prime(self):
|
|
412
419
|
n = istr.interpret_as_int(self)
|
|
413
|
-
if n <
|
|
420
|
+
if n < 1_000_000:
|
|
414
421
|
return n in istr._primes_up_to_1_000_000_as_set()
|
|
415
422
|
|
|
416
423
|
if not n & 1:
|
|
@@ -451,7 +458,7 @@ class istr(str):
|
|
|
451
458
|
if sieve[i]:
|
|
452
459
|
sieve[i * i : ub + 1 : i] = b"\x00" * (((ub - i * i) // i) + 1)
|
|
453
460
|
|
|
454
|
-
return list(map(cls, ([i for i, is_prime in enumerate(sieve) if is_prime and lb <= i < ub])))
|
|
461
|
+
return list(map(cls, ([i for i, is_prime in enumerate(sieve) if is_prime and lb <= i < ub]))) # range check just to be sure
|
|
455
462
|
|
|
456
463
|
@classmethod
|
|
457
464
|
@functools.lru_cache
|
|
@@ -483,11 +490,11 @@ class istr(str):
|
|
|
483
490
|
return n == 1
|
|
484
491
|
case 1:
|
|
485
492
|
return True
|
|
486
|
-
case
|
|
487
|
-
raise ValueError(f"exponent must be >=
|
|
493
|
+
case x if x < 0:
|
|
494
|
+
raise ValueError(f"exponent must be >=0; not {exponent}")
|
|
488
495
|
case _ if not isinstance(exponent, int):
|
|
489
496
|
raise TypeError(f"exponent must be int; not {type(exponent)}")
|
|
490
|
-
case _ if n <
|
|
497
|
+
case _ if n < 1_000_000:
|
|
491
498
|
return n in istr._power_ofs_up_to_1_000_000_as_set(exponent)
|
|
492
499
|
case _:
|
|
493
500
|
...
|
|
@@ -523,7 +530,7 @@ class istr(str):
|
|
|
523
530
|
result = []
|
|
524
531
|
case 1:
|
|
525
532
|
result = cls(list(range(lb, ub)))
|
|
526
|
-
case
|
|
533
|
+
case x if (x % 2 == 0 or lb >= 0) and ub <= 1_000_000:
|
|
527
534
|
result = in_range(cls._power_ofs_up_to_1_000_000(exponent), lb, ub)
|
|
528
535
|
case _:
|
|
529
536
|
result = cls._power_ofs(exponent, lb, ub)
|
|
@@ -532,10 +539,10 @@ class istr(str):
|
|
|
532
539
|
return result
|
|
533
540
|
|
|
534
541
|
@classmethod
|
|
535
|
-
def _power_ofs(cls,
|
|
536
|
-
if
|
|
542
|
+
def _power_ofs(cls, exponent, lb, ub):
|
|
543
|
+
if exponent % 2 == 0:
|
|
537
544
|
lb = max(0, lb)
|
|
538
|
-
match
|
|
545
|
+
match exponent:
|
|
539
546
|
case 0:
|
|
540
547
|
if lb <= 1 < ub:
|
|
541
548
|
result = [1]
|
|
@@ -546,11 +553,11 @@ class istr(str):
|
|
|
546
553
|
case _:
|
|
547
554
|
result = []
|
|
548
555
|
if lb < 0: # can't be the case for even n (because of above limiting)
|
|
549
|
-
i = -int((-lb) ** (1 /
|
|
556
|
+
i = -int((-lb) ** (1 / exponent))
|
|
550
557
|
else:
|
|
551
|
-
i = int(lb ** (1 /
|
|
552
|
-
while (i_n := i**
|
|
553
|
-
if i_n >= lb:
|
|
558
|
+
i = int(lb ** (1 / exponent))
|
|
559
|
+
while (i_n := i**exponent) < ub:
|
|
560
|
+
if i_n >= lb: # just to be sure
|
|
554
561
|
result.append(i_n)
|
|
555
562
|
i += 1
|
|
556
563
|
|
|
@@ -573,8 +580,7 @@ class istr(str):
|
|
|
573
580
|
same one-letter variables represent the the same character
|
|
574
581
|
the istr must have the same length as the letters
|
|
575
582
|
"""
|
|
576
|
-
|
|
577
|
-
namespace = inspect.currentframe().f_back.f_globals
|
|
583
|
+
namespace = get_namespace(namespace)
|
|
578
584
|
|
|
579
585
|
lookup = {}
|
|
580
586
|
for letter, ch in zip(letters, self):
|
|
@@ -592,12 +598,11 @@ class istr(str):
|
|
|
592
598
|
"""
|
|
593
599
|
compose an istr from individual letter variables
|
|
594
600
|
"""
|
|
595
|
-
|
|
596
|
-
namespace = inspect.currentframe().f_back.f_globals
|
|
597
|
-
namespace |= {ch: ch for ch in "0123456789"}
|
|
601
|
+
namespace = get_namespace(namespace) | {ch: ch for ch in "0123456789_"}
|
|
598
602
|
for letter in letters:
|
|
599
|
-
if letter
|
|
600
|
-
|
|
603
|
+
if letter.isidentifier():
|
|
604
|
+
if letter not in namespace:
|
|
605
|
+
raise ValueError(f"variable {repr(letter)} not defined")
|
|
601
606
|
s = "".join(str(namespace[letter]) for letter in letters)
|
|
602
607
|
return cls(s)
|
|
603
608
|
|
|
@@ -924,16 +929,22 @@ def in_range(lst, lb, ub):
|
|
|
924
929
|
|
|
925
930
|
def get_namespace(namespace):
|
|
926
931
|
if namespace is None:
|
|
927
|
-
frame =
|
|
928
|
-
while frame:
|
|
929
|
-
module_name = frame.f_globals.get("__name__")
|
|
930
|
-
if module_name != __name__:
|
|
931
|
-
break
|
|
932
|
-
frame = frame.f_back
|
|
932
|
+
frame = real_caller_frame()
|
|
933
933
|
namespace = frame.f_globals
|
|
934
934
|
return namespace
|
|
935
935
|
|
|
936
936
|
|
|
937
|
+
def real_caller_frame():
|
|
938
|
+
# this will return the frame of the first frame on the stack that does not belong to this module,
|
|
939
|
+
# so in the 'user' space
|
|
940
|
+
frame = inspect.currentframe()
|
|
941
|
+
frame_name = frame.f_globals.get("__name__")
|
|
942
|
+
frame = frame.f_back
|
|
943
|
+
while frame is not None and frame_name == frame.f_globals.get("__name__"):
|
|
944
|
+
frame = frame.f_back
|
|
945
|
+
return frame
|
|
946
|
+
|
|
947
|
+
|
|
937
948
|
istr.type = type(istr(0))
|
|
938
949
|
|
|
939
950
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: istr-python
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.26
|
|
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
|
|
@@ -379,6 +379,22 @@ It is also possible to test for even/odd of an ordinary int:
|
|
|
379
379
|
istr.is_even(4) ==> True
|
|
380
380
|
istr.is_odd(5) ==> True
|
|
381
381
|
```
|
|
382
|
+
|
|
383
|
+
#### test for palindrome
|
|
384
|
+
|
|
385
|
+
It is possible to test whether an istr is palindromic, like
|
|
386
|
+
```
|
|
387
|
+
istr(12321).is_palindrome() ==> True
|
|
388
|
+
istr('aba').is_palindrome() ==> True
|
|
389
|
+
istr(123).is_palindrome() ==> False
|
|
390
|
+
```
|
|
391
|
+
It is also possible to test for a palindrome for anything that can be converted to a str:
|
|
392
|
+
```
|
|
393
|
+
istr.is_palindrome(121) ==> True
|
|
394
|
+
istr.is_palindrome('no devil lived on') ==> True
|
|
395
|
+
istr.is_palindrome(min) ==> False
|
|
396
|
+
```
|
|
397
|
+
|
|
382
398
|
#### test for divisibility
|
|
383
399
|
|
|
384
400
|
It is possible to test whether an istr is divisible by a given value with the `is_divisible_by method,` e.g.
|
|
@@ -332,6 +332,16 @@ def test_even_odd():
|
|
|
332
332
|
assert istr.is_odd(11111111)
|
|
333
333
|
|
|
334
334
|
|
|
335
|
+
def test_is_palindrome():
|
|
336
|
+
assert istr(121).is_palindrome()
|
|
337
|
+
assert istr(1234321).is_palindrome()
|
|
338
|
+
assert not istr(123).is_palindrome()
|
|
339
|
+
assert istr('aba').is_palindrome()
|
|
340
|
+
assert not istr('abc').is_palindrome()
|
|
341
|
+
assert istr('').is_palindrome()
|
|
342
|
+
assert istr.is_palindrome('121')
|
|
343
|
+
assert istr.is_palindrome(121)
|
|
344
|
+
|
|
335
345
|
def test_is_divisible_by():
|
|
336
346
|
assert istr(18).is_divisible_by(3)
|
|
337
347
|
assert istr(18).is_divisible_by(istr(3))
|
|
@@ -964,9 +974,10 @@ def test_compose():
|
|
|
964
974
|
assert istr(":=xyz").equals(istr(123))
|
|
965
975
|
assert xyz.equals(istr(123))
|
|
966
976
|
|
|
967
|
-
assert istr(":=
|
|
968
|
-
assert
|
|
969
|
-
|
|
977
|
+
assert istr(":=xyz_000").equals(istr('123_000'))
|
|
978
|
+
assert xyz_000.equals(istr('123_000'))
|
|
979
|
+
assert xyz_000==123000
|
|
980
|
+
|
|
970
981
|
with pytest.raises(ValueError, match=re.escape(f"'0xyz' is not a valid identifier")):
|
|
971
982
|
istr(":=0xyz")
|
|
972
983
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|