istr-python 1.1.28__tar.gz → 1.1.30__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.28
3
+ Version: 1.1.30
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
@@ -335,7 +335,7 @@ several other types:
335
335
  ```
336
336
  istr([0, 1, 4]) ==> [istr('0'), istr('1'), istr('4')]
337
337
  istr((0, 1, 4)) ==> (istr('0'), istr('1'), istr('4'))
338
- istr({0, 1, 4}) ==> `{istr('4'), istr('0'), istr('1')} # or similar
338
+ istr({0, 1, 4}) ==> {istr('4'), istr('0'), istr('1')} # or similar
339
339
  ```
340
340
 
341
341
  - if a range, an istr.range instance will be returned
@@ -430,7 +430,7 @@ unless the *fallback* (last argument) is given, in which case *fallback* will be
430
430
  istr(18).divided_by(3) ==> 6 (actually istr("6"))
431
431
  istr(18).divided_by(istr(3)) ==> 6
432
432
  istr(19).divided_by(3) ==> None
433
- istr(19).divided_by(3, 0) ==>
433
+ istr(19).divided_by(3, 0) ==> 0
434
434
  istr(19).divided_by(3) ==> None
435
435
  istr(19).divided_by(istr(3)) ==> None
436
436
  istr.divided_by(18, 3) ==> 6
@@ -461,7 +461,7 @@ istr(28).is_cube()) ==> False
461
461
  It is also possible to test for cube of an ordinary int:
462
462
  ```
463
463
  istr.is_cube(27) ==> True
464
- istr.is_cube(28 ==> False
464
+ istr.is_cube(28) ==> False
465
465
  ```
466
466
 
467
467
  #### test for power of
@@ -544,9 +544,50 @@ istr('0456')[::-1] ==> istr('6540')
544
544
  > It is possible to reverse a negative istr, but the result can't be interpreted as an int anymore.
545
545
  >
546
546
  > ```
547
+ > istr(-456).reversed() ==> istr('654-')
547
548
  > istr(-456).reversed() + 3 ==> TypeError
548
549
  > ```
549
550
 
551
+
552
+ #### ceil
553
+
554
+ The `istr.ceil` method can be used to find the smallest integer, divisible by a given number (divisible_by), greater than or equal to the value.
555
+ This can be useful to step through all multiples of n, >= m, like:
556
+
557
+ ```
558
+ for i in istr.range(istr(1000/3, 10000, 3)) ==> # 1002, 1005, ... 9999
559
+ for i in istr.count(int(istr,ceil(1000/3)), 3)) ==> 1002, 1005, ...
560
+ ```
561
+ Examples:
562
+ ```
563
+ istr(1000).ceil() ==> 1000 # divisible_by is 1 by default
564
+ istr(1000).ceil(2) ==> 1000
565
+ istr(1000).ceil(3) ==> 1002
566
+ ```
567
+ It is also possible to use the ceil method for floats or ints:
568
+ ```
569
+ istr.ceil(1000.2) ==> 1001
570
+ istr.ceil(1000.2, 2) ==> 1002
571
+ istr.ceil(1000.2, 3 ==> 1002
572
+ ```
573
+
574
+ #### floor
575
+
576
+ The `istr.floor` method can be used to find the largest integer, divisible by a given number (divisible_by), smaller than or equal to the value.
577
+
578
+ Examples:
579
+ ```
580
+ istr(1000).floor() ==> 1000 # divisible_by is 1 by default
581
+ istr(1000).floor(2) ==> 1000
582
+ istr(1000).floor(3) ==> 999
583
+ ```
584
+ It is also possible to use the ceil method for floats or ints:
585
+ ```
586
+ istr.floor(1000.2) ==> 1000
587
+ istr.floor(1000.2, 2) ==> 1000
588
+ istr.floor(1000.2, 3 ==> 999
589
+ ```
590
+
550
591
  #### enumerate with istrs
551
592
 
552
593
  The `istr.enumerate` class method can be used just as the built-in enumerate function.
@@ -737,7 +778,7 @@ To decompose an istr into individual variables, it is arguably easier and safer
737
778
  a, b, c = istr(485)
738
779
  ```
739
780
 
740
- With `istr.compose()`, an istr can be constructed from individual (global) variables and digits.
781
+ With `istr.compose()`, an istr can be constructed from individual (global) variables and letters that can't be identifiers.
741
782
  E.g.
742
783
 
743
784
  ```
@@ -746,17 +787,19 @@ y = 9
746
787
  z = 6
747
788
  test1 = istr.compose("xyz")
748
789
  test2 = istr.compose("xyz0")
790
+ test3 = istr.compose("(xyz)")
749
791
  ```
750
- Now, `test1` will be `istr(396)` and `test2` will be `istr(3960)`.
792
+ Now, `test1` will be `istr(396)`, `test2` will be `istr(3960)` and `test3` will be `istr("(396)")`.
751
793
 
752
- Composing can also be done by prefixing a string with '=', like:
794
+ Composing can also be done by prefixing a string with `=`, like:
753
795
 
754
796
  ```
755
797
  test1 = istr("=xyz")
756
798
  test2 = istr("=xyz0")
757
-
758
- Now, `test1` will be `istr(396)` and `test2` will be `istr(3960)`.
799
+ test3 = istr("=(xyz)")
759
800
  ```
801
+ Now, `test1` will be `istr(396)`, `test2` will be `istr(3960)` and `test3` will be `istr("(396)")`.
802
+
760
803
  Note that `str(istr("="))` is "=".
761
804
 
762
805
  Composing and assignment can be done by prefixing a string with ':=', like:
@@ -947,31 +990,32 @@ operator/function int str Example
947
990
  + x istr(20) + 3 ==> istr('23')
948
991
  _ x istr(20) - 3 ==> istr('17')
949
992
  * x istr(20) * 3 ==> istr('60')
950
- / x istr(20) / 3 ==> istr('6')
951
- // x istr(20) // 3 ==> istr('6')
952
- % x istr(20) % 3 ==> istr('2')
953
- divmod x divmod(istr(20), 3) ==> (istr('6'), istr('2'))
954
- ** x istr(2) ** 3 ==> istr('8')
955
- <=, <, >, >= x istr('100') > istr('2') ==> True
956
- abs x abs(istr(-20)) ==> istr('20')
957
- int x int(istr("20")) ==> 20
958
- float x float(istr("20")) ==> 20.0
959
- complex x complex(istr("20")) ==> (20+0j)
960
- == x x istr(20) == 20 ==> True | istr(20) == '20' ==> True
961
- bool x x *) bool(istr(' 0 ')) ==> False | bool(istr('')) ==> False
962
- @ x istr(20) @ 3 ==> istr('202020')
963
- | x istr(20) | '5' ==> istr('205')
964
- slicing x istr(12345)[1:3] ==> istr('23')
965
- iterate x [x for x in istr(20)] ==> [istr('2'), istr('0')]
966
- len x len(istr(' 20 ')) ==> 4
967
- count x istr(100).count(0) ==> 2
968
- index x istr(' 100 ').index('0') ==> 2
969
- split x istr('1 2').split() ==> (istr('1'), istr('2'))
970
- string format x f"|{istr(1234):6}|" ==> '|1234 |'
971
- other string methods x istr('aAbBcC').lower() ==> istr('aabbcc')
972
- istr('aAbBcC').islower() ==> False
973
- istr(' abc ').strip() ==> istr('abc')
974
- ...
993
+ / x istr(20) / 3 ==> istr('6')
994
+ // x istr(20) // 3 ==> istr('6')
995
+ % x istr(20) % 3 ==> istr('2')
996
+ divmod x divmod(istr(20), 3) ==> (istr('6'), istr('2'))
997
+ ** x istr(2) ** 3 ==> istr('8')
998
+ <=, <, >, >= x istr('100') > istr('2') ==> True
999
+ abs x abs(istr(-20)) ==> istr('20')
1000
+ int x int(istr("20")) ==> 20
1001
+ float x float(istr("20")) ==> 20.0
1002
+ complex x complex(istr("20")) ==> (20+0j)
1003
+ == x x istr(20) == 20 ==> True | istr(20) == '20' ==> True
1004
+ bool x x *) bool(istr(' 0 ')) ==> False | bool(istr('')) ==> False
1005
+ @ x istr(20) @ 3 ==> istr('202020')
1006
+ | x istr(20) | '5' ==> istr('205')
1007
+ slicing x istr(12345)[1:3] ==> istr('23')
1008
+ iterate x [x for x in istr(20)] ==> [istr('2'), istr('0')]
1009
+ len x len(istr(' 20 ')) ==> 4
1010
+ count x istr(100).count(0) ==> 2
1011
+ istr.count(100) ==> istr('100'), istr('101'). istr('102'), ...
1012
+ index x istr(' 100 ').index('0') ==> 2
1013
+ split x istr('1 2').split() ==> (istr('1'), istr('2'))
1014
+ string format x f"|{istr(1234):6}|" ==> '|1234 |'
1015
+ other string methods x istr('aAbBcC').lower() ==> istr('aabbcc')
1016
+ istr('aAbBcC').islower() ==> False
1017
+ istr(' abc ').strip() ==> istr('abc')
1018
+ ...
975
1019
  -----------------------------------------------------------------------------------------
976
1020
  *) str is applied if is_int() is False
977
1021
  ```
@@ -322,7 +322,7 @@ several other types:
322
322
  ```
323
323
  istr([0, 1, 4]) ==> [istr('0'), istr('1'), istr('4')]
324
324
  istr((0, 1, 4)) ==> (istr('0'), istr('1'), istr('4'))
325
- istr({0, 1, 4}) ==> `{istr('4'), istr('0'), istr('1')} # or similar
325
+ istr({0, 1, 4}) ==> {istr('4'), istr('0'), istr('1')} # or similar
326
326
  ```
327
327
 
328
328
  - if a range, an istr.range instance will be returned
@@ -417,7 +417,7 @@ unless the *fallback* (last argument) is given, in which case *fallback* will be
417
417
  istr(18).divided_by(3) ==> 6 (actually istr("6"))
418
418
  istr(18).divided_by(istr(3)) ==> 6
419
419
  istr(19).divided_by(3) ==> None
420
- istr(19).divided_by(3, 0) ==>
420
+ istr(19).divided_by(3, 0) ==> 0
421
421
  istr(19).divided_by(3) ==> None
422
422
  istr(19).divided_by(istr(3)) ==> None
423
423
  istr.divided_by(18, 3) ==> 6
@@ -448,7 +448,7 @@ istr(28).is_cube()) ==> False
448
448
  It is also possible to test for cube of an ordinary int:
449
449
  ```
450
450
  istr.is_cube(27) ==> True
451
- istr.is_cube(28 ==> False
451
+ istr.is_cube(28) ==> False
452
452
  ```
453
453
 
454
454
  #### test for power of
@@ -531,9 +531,50 @@ istr('0456')[::-1] ==> istr('6540')
531
531
  > It is possible to reverse a negative istr, but the result can't be interpreted as an int anymore.
532
532
  >
533
533
  > ```
534
+ > istr(-456).reversed() ==> istr('654-')
534
535
  > istr(-456).reversed() + 3 ==> TypeError
535
536
  > ```
536
537
 
538
+
539
+ #### ceil
540
+
541
+ The `istr.ceil` method can be used to find the smallest integer, divisible by a given number (divisible_by), greater than or equal to the value.
542
+ This can be useful to step through all multiples of n, >= m, like:
543
+
544
+ ```
545
+ for i in istr.range(istr(1000/3, 10000, 3)) ==> # 1002, 1005, ... 9999
546
+ for i in istr.count(int(istr,ceil(1000/3)), 3)) ==> 1002, 1005, ...
547
+ ```
548
+ Examples:
549
+ ```
550
+ istr(1000).ceil() ==> 1000 # divisible_by is 1 by default
551
+ istr(1000).ceil(2) ==> 1000
552
+ istr(1000).ceil(3) ==> 1002
553
+ ```
554
+ It is also possible to use the ceil method for floats or ints:
555
+ ```
556
+ istr.ceil(1000.2) ==> 1001
557
+ istr.ceil(1000.2, 2) ==> 1002
558
+ istr.ceil(1000.2, 3 ==> 1002
559
+ ```
560
+
561
+ #### floor
562
+
563
+ The `istr.floor` method can be used to find the largest integer, divisible by a given number (divisible_by), smaller than or equal to the value.
564
+
565
+ Examples:
566
+ ```
567
+ istr(1000).floor() ==> 1000 # divisible_by is 1 by default
568
+ istr(1000).floor(2) ==> 1000
569
+ istr(1000).floor(3) ==> 999
570
+ ```
571
+ It is also possible to use the ceil method for floats or ints:
572
+ ```
573
+ istr.floor(1000.2) ==> 1000
574
+ istr.floor(1000.2, 2) ==> 1000
575
+ istr.floor(1000.2, 3 ==> 999
576
+ ```
577
+
537
578
  #### enumerate with istrs
538
579
 
539
580
  The `istr.enumerate` class method can be used just as the built-in enumerate function.
@@ -724,7 +765,7 @@ To decompose an istr into individual variables, it is arguably easier and safer
724
765
  a, b, c = istr(485)
725
766
  ```
726
767
 
727
- With `istr.compose()`, an istr can be constructed from individual (global) variables and digits.
768
+ With `istr.compose()`, an istr can be constructed from individual (global) variables and letters that can't be identifiers.
728
769
  E.g.
729
770
 
730
771
  ```
@@ -733,17 +774,19 @@ y = 9
733
774
  z = 6
734
775
  test1 = istr.compose("xyz")
735
776
  test2 = istr.compose("xyz0")
777
+ test3 = istr.compose("(xyz)")
736
778
  ```
737
- Now, `test1` will be `istr(396)` and `test2` will be `istr(3960)`.
779
+ Now, `test1` will be `istr(396)`, `test2` will be `istr(3960)` and `test3` will be `istr("(396)")`.
738
780
 
739
- Composing can also be done by prefixing a string with '=', like:
781
+ Composing can also be done by prefixing a string with `=`, like:
740
782
 
741
783
  ```
742
784
  test1 = istr("=xyz")
743
785
  test2 = istr("=xyz0")
744
-
745
- Now, `test1` will be `istr(396)` and `test2` will be `istr(3960)`.
786
+ test3 = istr("=(xyz)")
746
787
  ```
788
+ Now, `test1` will be `istr(396)`, `test2` will be `istr(3960)` and `test3` will be `istr("(396)")`.
789
+
747
790
  Note that `str(istr("="))` is "=".
748
791
 
749
792
  Composing and assignment can be done by prefixing a string with ':=', like:
@@ -934,31 +977,32 @@ operator/function int str Example
934
977
  + x istr(20) + 3 ==> istr('23')
935
978
  _ x istr(20) - 3 ==> istr('17')
936
979
  * x istr(20) * 3 ==> istr('60')
937
- / x istr(20) / 3 ==> istr('6')
938
- // x istr(20) // 3 ==> istr('6')
939
- % x istr(20) % 3 ==> istr('2')
940
- divmod x divmod(istr(20), 3) ==> (istr('6'), istr('2'))
941
- ** x istr(2) ** 3 ==> istr('8')
942
- <=, <, >, >= x istr('100') > istr('2') ==> True
943
- abs x abs(istr(-20)) ==> istr('20')
944
- int x int(istr("20")) ==> 20
945
- float x float(istr("20")) ==> 20.0
946
- complex x complex(istr("20")) ==> (20+0j)
947
- == x x istr(20) == 20 ==> True | istr(20) == '20' ==> True
948
- bool x x *) bool(istr(' 0 ')) ==> False | bool(istr('')) ==> False
949
- @ x istr(20) @ 3 ==> istr('202020')
950
- | x istr(20) | '5' ==> istr('205')
951
- slicing x istr(12345)[1:3] ==> istr('23')
952
- iterate x [x for x in istr(20)] ==> [istr('2'), istr('0')]
953
- len x len(istr(' 20 ')) ==> 4
954
- count x istr(100).count(0) ==> 2
955
- index x istr(' 100 ').index('0') ==> 2
956
- split x istr('1 2').split() ==> (istr('1'), istr('2'))
957
- string format x f"|{istr(1234):6}|" ==> '|1234 |'
958
- other string methods x istr('aAbBcC').lower() ==> istr('aabbcc')
959
- istr('aAbBcC').islower() ==> False
960
- istr(' abc ').strip() ==> istr('abc')
961
- ...
980
+ / x istr(20) / 3 ==> istr('6')
981
+ // x istr(20) // 3 ==> istr('6')
982
+ % x istr(20) % 3 ==> istr('2')
983
+ divmod x divmod(istr(20), 3) ==> (istr('6'), istr('2'))
984
+ ** x istr(2) ** 3 ==> istr('8')
985
+ <=, <, >, >= x istr('100') > istr('2') ==> True
986
+ abs x abs(istr(-20)) ==> istr('20')
987
+ int x int(istr("20")) ==> 20
988
+ float x float(istr("20")) ==> 20.0
989
+ complex x complex(istr("20")) ==> (20+0j)
990
+ == x x istr(20) == 20 ==> True | istr(20) == '20' ==> True
991
+ bool x x *) bool(istr(' 0 ')) ==> False | bool(istr('')) ==> False
992
+ @ x istr(20) @ 3 ==> istr('202020')
993
+ | x istr(20) | '5' ==> istr('205')
994
+ slicing x istr(12345)[1:3] ==> istr('23')
995
+ iterate x [x for x in istr(20)] ==> [istr('2'), istr('0')]
996
+ len x len(istr(' 20 ')) ==> 4
997
+ count x istr(100).count(0) ==> 2
998
+ istr.count(100) ==> istr('100'), istr('101'). istr('102'), ...
999
+ index x istr(' 100 ').index('0') ==> 2
1000
+ split x istr('1 2').split() ==> (istr('1'), istr('2'))
1001
+ string format x f"|{istr(1234):6}|" ==> '|1234 |'
1002
+ other string methods x istr('aAbBcC').lower() ==> istr('aabbcc')
1003
+ istr('aAbBcC').islower() ==> False
1004
+ istr(' abc ').strip() ==> istr('abc')
1005
+ ...
962
1006
  -----------------------------------------------------------------------------------------
963
1007
  *) str is applied if is_int() is False
964
1008
  ```
@@ -5,7 +5,7 @@
5
5
  # |_||___/ \__||_|
6
6
  # strings you can count on
7
7
 
8
- __version__ = "1.1.28"
8
+ __version__ = "1.1.30"
9
9
  import functools
10
10
  import itertools
11
11
  import types
@@ -600,14 +600,16 @@ class istr(str):
600
600
  namespace = get_namespace(namespace)
601
601
 
602
602
  lookup = {}
603
+
604
+ if len(letters) != len(self):
605
+ raise ValueError(f"incorrect number of variables {len(letters)}; should be {len(self)}")
606
+
603
607
  for letter, ch in zip(letters, self):
604
608
  if letter in lookup and lookup[letter] != ch:
605
609
  raise ValueError(f"multiple values found for variable {letter}")
606
610
  if not letter.isidentifier():
607
611
  raise ValueError(f"{repr(letter)} cannot be used as a variable")
608
612
  lookup[str(letter)] = ch
609
- if len(letters) != len(self):
610
- raise ValueError(f"incorrect number of variables {len(letters)}; should be {len(self)}")
611
613
  namespace.update(lookup)
612
614
 
613
615
  @classmethod
@@ -615,13 +617,16 @@ class istr(str):
615
617
  """
616
618
  compose an istr from individual letter variables
617
619
  """
618
- namespace = get_namespace(namespace) | {ch: ch for ch in "0123456789_"}
620
+ namespace = get_namespace(namespace)
621
+ result=[]
619
622
  for letter in letters:
620
623
  if letter.isidentifier():
621
624
  if letter not in namespace:
622
625
  raise ValueError(f"variable {repr(letter)} not defined")
623
- s = "".join(str(namespace[letter]) for letter in letters)
624
- return cls(s)
626
+ result.append(str(namespace[letter]))
627
+ else:
628
+ result.append(letter)
629
+ return cls("".join(result))
625
630
 
626
631
  def __or__(self, other):
627
632
  if isinstance(other, str):
@@ -672,6 +677,22 @@ class istr(str):
672
677
 
673
678
  def reversed(self):
674
679
  return self[::-1]
680
+
681
+ def ceil(self, divisible_by=1):
682
+ if divisible_by<=0:
683
+ raise ValueError(f"step has to be >0, not {divisible_by}")
684
+ if divisible_by!=int(divisible_by):
685
+ raise ValueError(f"step has to be an integer value, not {divisible_by}")
686
+ n = istr.interpret_as_float(self)
687
+ return istr((math.ceil(n/divisible_by))*divisible_by)
688
+
689
+ def floor(self, divisible_by=1):
690
+ if divisible_by<=0:
691
+ raise ValueError(f"step has to be >0, not {divisible_by}")
692
+ if divisible_by!=int(divisible_by):
693
+ raise ValueError(f"step has to be an integer value, not {divisible_by}")
694
+ return istr((math.floor(self/divisible_by))*divisible_by)
695
+
675
696
 
676
697
  def interpret_as_int(self):
677
698
  if isinstance(self, istr):
@@ -682,6 +703,16 @@ class istr(str):
682
703
  n = int(self)
683
704
  return n
684
705
 
706
+
707
+ def interpret_as_float(self):
708
+ if isinstance(self, istr):
709
+ if not self.is_int():
710
+ raise TypeError(f"not interpretable as float: {self._frepr(self)}")
711
+ n = self._as_int
712
+ else:
713
+ n = float(self)
714
+ return n
715
+
685
716
  def _str_method(self, name, *args, **kwargs):
686
717
  return self.__class__(getattr(super(), name)(*args, **kwargs))
687
718
 
@@ -762,7 +793,8 @@ class istr(str):
762
793
 
763
794
  cls._int_format = int_format
764
795
 
765
- def __enter__(self): ...
796
+ def __enter__(self):
797
+ ...
766
798
 
767
799
  def __exit__(self, exc_type, exc_value, exc_tb):
768
800
  self.saved_cls._int_format = self.saved_int_format
@@ -783,7 +815,8 @@ class istr(str):
783
815
  self.saved_cls = cls
784
816
  cls._repr_mode = mode
785
817
 
786
- def __enter__(self): ...
818
+ def __enter__(self):
819
+ ...
787
820
 
788
821
  def __exit__(self, exc_type, exc_value, exc_tb):
789
822
  self.saved_cls._repr_mode = self.saved_repr_mode
@@ -802,7 +835,8 @@ class istr(str):
802
835
  self.saved_cls = cls
803
836
  cls._base = base
804
837
 
805
- def __enter__(self): ...
838
+ def __enter__(self):
839
+ ...
806
840
 
807
841
  def __exit__(self, exc_type, exc_value, exc_tb):
808
842
  self.saved_cls._base = self.saved_base
@@ -984,3 +1018,4 @@ class istrModule(types.ModuleType):
984
1018
 
985
1019
  if __name__ != "__main__":
986
1020
  sys.modules["istr"].__class__ = istrModule
1021
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: istr-python
3
- Version: 1.1.28
3
+ Version: 1.1.30
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
@@ -335,7 +335,7 @@ several other types:
335
335
  ```
336
336
  istr([0, 1, 4]) ==> [istr('0'), istr('1'), istr('4')]
337
337
  istr((0, 1, 4)) ==> (istr('0'), istr('1'), istr('4'))
338
- istr({0, 1, 4}) ==> `{istr('4'), istr('0'), istr('1')} # or similar
338
+ istr({0, 1, 4}) ==> {istr('4'), istr('0'), istr('1')} # or similar
339
339
  ```
340
340
 
341
341
  - if a range, an istr.range instance will be returned
@@ -430,7 +430,7 @@ unless the *fallback* (last argument) is given, in which case *fallback* will be
430
430
  istr(18).divided_by(3) ==> 6 (actually istr("6"))
431
431
  istr(18).divided_by(istr(3)) ==> 6
432
432
  istr(19).divided_by(3) ==> None
433
- istr(19).divided_by(3, 0) ==>
433
+ istr(19).divided_by(3, 0) ==> 0
434
434
  istr(19).divided_by(3) ==> None
435
435
  istr(19).divided_by(istr(3)) ==> None
436
436
  istr.divided_by(18, 3) ==> 6
@@ -461,7 +461,7 @@ istr(28).is_cube()) ==> False
461
461
  It is also possible to test for cube of an ordinary int:
462
462
  ```
463
463
  istr.is_cube(27) ==> True
464
- istr.is_cube(28 ==> False
464
+ istr.is_cube(28) ==> False
465
465
  ```
466
466
 
467
467
  #### test for power of
@@ -544,9 +544,50 @@ istr('0456')[::-1] ==> istr('6540')
544
544
  > It is possible to reverse a negative istr, but the result can't be interpreted as an int anymore.
545
545
  >
546
546
  > ```
547
+ > istr(-456).reversed() ==> istr('654-')
547
548
  > istr(-456).reversed() + 3 ==> TypeError
548
549
  > ```
549
550
 
551
+
552
+ #### ceil
553
+
554
+ The `istr.ceil` method can be used to find the smallest integer, divisible by a given number (divisible_by), greater than or equal to the value.
555
+ This can be useful to step through all multiples of n, >= m, like:
556
+
557
+ ```
558
+ for i in istr.range(istr(1000/3, 10000, 3)) ==> # 1002, 1005, ... 9999
559
+ for i in istr.count(int(istr,ceil(1000/3)), 3)) ==> 1002, 1005, ...
560
+ ```
561
+ Examples:
562
+ ```
563
+ istr(1000).ceil() ==> 1000 # divisible_by is 1 by default
564
+ istr(1000).ceil(2) ==> 1000
565
+ istr(1000).ceil(3) ==> 1002
566
+ ```
567
+ It is also possible to use the ceil method for floats or ints:
568
+ ```
569
+ istr.ceil(1000.2) ==> 1001
570
+ istr.ceil(1000.2, 2) ==> 1002
571
+ istr.ceil(1000.2, 3 ==> 1002
572
+ ```
573
+
574
+ #### floor
575
+
576
+ The `istr.floor` method can be used to find the largest integer, divisible by a given number (divisible_by), smaller than or equal to the value.
577
+
578
+ Examples:
579
+ ```
580
+ istr(1000).floor() ==> 1000 # divisible_by is 1 by default
581
+ istr(1000).floor(2) ==> 1000
582
+ istr(1000).floor(3) ==> 999
583
+ ```
584
+ It is also possible to use the ceil method for floats or ints:
585
+ ```
586
+ istr.floor(1000.2) ==> 1000
587
+ istr.floor(1000.2, 2) ==> 1000
588
+ istr.floor(1000.2, 3 ==> 999
589
+ ```
590
+
550
591
  #### enumerate with istrs
551
592
 
552
593
  The `istr.enumerate` class method can be used just as the built-in enumerate function.
@@ -737,7 +778,7 @@ To decompose an istr into individual variables, it is arguably easier and safer
737
778
  a, b, c = istr(485)
738
779
  ```
739
780
 
740
- With `istr.compose()`, an istr can be constructed from individual (global) variables and digits.
781
+ With `istr.compose()`, an istr can be constructed from individual (global) variables and letters that can't be identifiers.
741
782
  E.g.
742
783
 
743
784
  ```
@@ -746,17 +787,19 @@ y = 9
746
787
  z = 6
747
788
  test1 = istr.compose("xyz")
748
789
  test2 = istr.compose("xyz0")
790
+ test3 = istr.compose("(xyz)")
749
791
  ```
750
- Now, `test1` will be `istr(396)` and `test2` will be `istr(3960)`.
792
+ Now, `test1` will be `istr(396)`, `test2` will be `istr(3960)` and `test3` will be `istr("(396)")`.
751
793
 
752
- Composing can also be done by prefixing a string with '=', like:
794
+ Composing can also be done by prefixing a string with `=`, like:
753
795
 
754
796
  ```
755
797
  test1 = istr("=xyz")
756
798
  test2 = istr("=xyz0")
757
-
758
- Now, `test1` will be `istr(396)` and `test2` will be `istr(3960)`.
799
+ test3 = istr("=(xyz)")
759
800
  ```
801
+ Now, `test1` will be `istr(396)`, `test2` will be `istr(3960)` and `test3` will be `istr("(396)")`.
802
+
760
803
  Note that `str(istr("="))` is "=".
761
804
 
762
805
  Composing and assignment can be done by prefixing a string with ':=', like:
@@ -947,31 +990,32 @@ operator/function int str Example
947
990
  + x istr(20) + 3 ==> istr('23')
948
991
  _ x istr(20) - 3 ==> istr('17')
949
992
  * x istr(20) * 3 ==> istr('60')
950
- / x istr(20) / 3 ==> istr('6')
951
- // x istr(20) // 3 ==> istr('6')
952
- % x istr(20) % 3 ==> istr('2')
953
- divmod x divmod(istr(20), 3) ==> (istr('6'), istr('2'))
954
- ** x istr(2) ** 3 ==> istr('8')
955
- <=, <, >, >= x istr('100') > istr('2') ==> True
956
- abs x abs(istr(-20)) ==> istr('20')
957
- int x int(istr("20")) ==> 20
958
- float x float(istr("20")) ==> 20.0
959
- complex x complex(istr("20")) ==> (20+0j)
960
- == x x istr(20) == 20 ==> True | istr(20) == '20' ==> True
961
- bool x x *) bool(istr(' 0 ')) ==> False | bool(istr('')) ==> False
962
- @ x istr(20) @ 3 ==> istr('202020')
963
- | x istr(20) | '5' ==> istr('205')
964
- slicing x istr(12345)[1:3] ==> istr('23')
965
- iterate x [x for x in istr(20)] ==> [istr('2'), istr('0')]
966
- len x len(istr(' 20 ')) ==> 4
967
- count x istr(100).count(0) ==> 2
968
- index x istr(' 100 ').index('0') ==> 2
969
- split x istr('1 2').split() ==> (istr('1'), istr('2'))
970
- string format x f"|{istr(1234):6}|" ==> '|1234 |'
971
- other string methods x istr('aAbBcC').lower() ==> istr('aabbcc')
972
- istr('aAbBcC').islower() ==> False
973
- istr(' abc ').strip() ==> istr('abc')
974
- ...
993
+ / x istr(20) / 3 ==> istr('6')
994
+ // x istr(20) // 3 ==> istr('6')
995
+ % x istr(20) % 3 ==> istr('2')
996
+ divmod x divmod(istr(20), 3) ==> (istr('6'), istr('2'))
997
+ ** x istr(2) ** 3 ==> istr('8')
998
+ <=, <, >, >= x istr('100') > istr('2') ==> True
999
+ abs x abs(istr(-20)) ==> istr('20')
1000
+ int x int(istr("20")) ==> 20
1001
+ float x float(istr("20")) ==> 20.0
1002
+ complex x complex(istr("20")) ==> (20+0j)
1003
+ == x x istr(20) == 20 ==> True | istr(20) == '20' ==> True
1004
+ bool x x *) bool(istr(' 0 ')) ==> False | bool(istr('')) ==> False
1005
+ @ x istr(20) @ 3 ==> istr('202020')
1006
+ | x istr(20) | '5' ==> istr('205')
1007
+ slicing x istr(12345)[1:3] ==> istr('23')
1008
+ iterate x [x for x in istr(20)] ==> [istr('2'), istr('0')]
1009
+ len x len(istr(' 20 ')) ==> 4
1010
+ count x istr(100).count(0) ==> 2
1011
+ istr.count(100) ==> istr('100'), istr('101'). istr('102'), ...
1012
+ index x istr(' 100 ').index('0') ==> 2
1013
+ split x istr('1 2').split() ==> (istr('1'), istr('2'))
1014
+ string format x f"|{istr(1234):6}|" ==> '|1234 |'
1015
+ other string methods x istr('aAbBcC').lower() ==> istr('aabbcc')
1016
+ istr('aAbBcC').islower() ==> False
1017
+ istr(' abc ').strip() ==> istr('abc')
1018
+ ...
975
1019
  -----------------------------------------------------------------------------------------
976
1020
  *) str is applied if is_int() is False
977
1021
  ```
@@ -10,7 +10,7 @@ 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.28"
13
+ version = "1.1.30"
14
14
  readme = "README.md"
15
15
  requires-python = ">=3.10"
16
16
  dependencies = []
@@ -987,13 +987,29 @@ def test_decompose():
987
987
  with pytest.raises(ValueError):
988
988
  istr(123).decompose("xy1")
989
989
 
990
-
990
+ def test_ceil():
991
+ assert istr(1000).ceil()==1000
992
+ assert istr(1000).ceil(1)==1000
993
+ assert istr(1000).ceil(2)==1000
994
+ assert istr(1000).ceil(3)==1002
995
+ assert istr.ceil(1000)==1000
996
+ assert istr.ceil(1000,1)==1000
997
+ assert istr.ceil(1000.2,1).equals(istr(1001))
998
+
999
+ def test_floor():
1000
+ assert istr(1000).floor()==1000
1001
+ assert istr(1000).floor(1)==1000
1002
+ assert istr(1000).floor(2)==1000
1003
+ assert istr(1000).floor(3)==999
1004
+ assert istr.floor(1000)==1000
1005
+ assert istr.floor(1000,1)==1000
1006
+ assert istr.floor(1000.2,1).equals(istr(1000))
1007
+
991
1008
  def test_compose():
1009
+ global x, y, z, _
992
1010
  x = 1
993
1011
  y = "2"
994
1012
  z = istr(3)
995
-
996
- assert istr.compose("xyz").equals(istr(123))
997
1013
  with pytest.raises(ValueError):
998
1014
  istr.compose("wxyz") # w is not defined
999
1015
  assert istr.compose("xyz", namespace=dict(x=3, y=istr(4), z="5")).equals(istr(345))
@@ -1015,7 +1031,10 @@ def test_compose():
1015
1031
  assert istr(":=xyz").equals(istr(123))
1016
1032
  assert xyz.equals(istr(123))
1017
1033
 
1018
- assert istr(":=xyz_000").equals(istr("123_000"))
1034
+ with pytest.raises(ValueError):
1035
+ istr("=123_000")
1036
+ _ = "_"
1037
+ xyz_000 = istr("=123_000")
1019
1038
  assert xyz_000.equals(istr("123_000"))
1020
1039
  assert xyz_000 == 123000
1021
1040
 
File without changes