99import string
1010import threading
1111
12- alphanums = string .digits + string .ascii_lowercase
12+ alphanums = " -" + string .digits + string . ascii_uppercase + "_" + string .ascii_lowercase
1313
1414
1515def safezip (* args ):
@@ -29,6 +29,11 @@ class ArithString:
2929 def new (cls , * args , ** kw ):
3030 return cls (* args , ** kw )
3131
32+ def range (self , other : "ArithString" , count : int ):
33+ assert isinstance (other , ArithString )
34+ checkpoints = split_space (self .int , other .int , count )
35+ return [self .new (int = i ) for i in checkpoints ]
36+
3237
3338class ArithUUID (UUID , ArithString ):
3439 "A UUID that supports basic arithmetic (add, sub)"
@@ -49,70 +54,96 @@ def __sub__(self, other: Union[UUID, int]):
4954 return NotImplemented
5055
5156
52- def numberToBase (num , base ) :
57+ def numberToAlphanum (num : int , base : str = alphanums ) -> str :
5358 digits = []
5459 while num > 0 :
55- num , remainder = divmod (num , base )
60+ num , remainder = divmod (num , len ( base ) )
5661 digits .append (remainder )
57- return "" .join (alphanums [i ] for i in digits [::- 1 ])
62+ return "" .join (base [i ] for i in digits [::- 1 ])
5863
5964
60- class ArithAlphanumeric (ArithString ):
61- def __init__ (self , str : str = None , int : int = None , max_len = None ):
62- if str is None :
63- str = numberToBase (int , len (alphanums ))
64- else :
65- assert int is None
65+ def alphanumToNumber (alphanum : str , base : str ) -> int :
66+ num = 0
67+ for c in alphanum :
68+ num = num * len (base ) + base .index (c )
69+ return num
70+
71+
72+ def justify_alphanums (s1 : str , s2 : str ):
73+ max_len = max (len (s1 ), len (s2 ))
74+ s1 = s1 .ljust (max_len )
75+ s2 = s2 .ljust (max_len )
76+ return s1 , s2
6677
67- if max_len and len (str ) > max_len :
78+
79+ def alphanums_to_numbers (s1 : str , s2 : str ):
80+ s1 , s2 = justify_alphanums (s1 , s2 )
81+ n1 = alphanumToNumber (s1 , alphanums )
82+ n2 = alphanumToNumber (s2 , alphanums )
83+ return n1 , n2
84+
85+
86+ class ArithAlphanumeric (ArithString ):
87+ def __init__ (self , s : str , max_len = None ):
88+ if s is None :
89+ raise ValueError ("Alphanum string cannot be None" )
90+ if max_len and len (s ) > max_len :
6891 raise ValueError (f"Length of alphanum value '{ str } ' is longer than the expected { max_len } " )
6992
70- self ._str = str
93+ for ch in s :
94+ if ch not in alphanums :
95+ raise ValueError (f"Unexpected character { ch } in alphanum string" )
96+
97+ self ._str = s
7198 self ._max_len = max_len
7299
73- @property
74- def int (self ):
75- return int (self ._str , len ( alphanums ) )
100+ # @property
101+ # def int(self):
102+ # return alphanumToNumber (self._str, alphanums)
76103
77104 def __str__ (self ):
78105 s = self ._str
79106 if self ._max_len :
80- s = s .rjust (self ._max_len , "0" )
107+ s = s .rjust (self ._max_len , alphanums [ 0 ] )
81108 return s
82109
83110 def __len__ (self ):
84111 return len (self ._str )
85112
86- def __int__ (self ):
87- return self .int
88-
89113 def __repr__ (self ):
90114 return f'alphanum"{ self ._str } "'
91115
92- def __add__ (self , other : "Union[ArithAlphanumeric, int]" ):
116+ def __add__ (self , other : "Union[ArithAlphanumeric, int]" ) -> "ArithAlphanumeric" :
93117 if isinstance (other , int ):
94- res = self .new (int = self .int + other )
95- if len (str (res )) != len (self ):
96- raise ValueError ("Overflow error when adding to alphanumeric" )
97- return res
118+ if other != 1 :
119+ raise NotImplementedError ("not implemented for arbitrary numbers" )
120+ lastchar = self ._str [- 1 ] if self ._str else alphanums [0 ]
121+ s = self ._str [:- 1 ] + alphanums [alphanums .index (lastchar ) + other ]
122+ return self .new (s )
98123 return NotImplemented
99124
100- def __sub__ (self , other : "Union[ArithAlphanumeric, int]" ):
101- if isinstance (other , int ):
102- return type (self )(int = self .int - other )
103- elif isinstance (other , ArithAlphanumeric ):
104- return self .int - other .int
125+ def range (self , other : "ArithAlphanumeric" , count : int ):
126+ assert isinstance (other , ArithAlphanumeric )
127+ n1 , n2 = alphanums_to_numbers (self ._str , other ._str )
128+ split = split_space (n1 , n2 , count )
129+ return [self .new (numberToAlphanum (s )) for s in split ]
130+
131+ def __sub__ (self , other : "Union[ArithAlphanumeric, int]" ) -> float :
132+ if isinstance (other , ArithAlphanumeric ):
133+ n1 , n2 = alphanums_to_numbers (self ._str , other ._str )
134+ return n1 - n2
135+
105136 return NotImplemented
106137
107138 def __ge__ (self , other ):
108139 if not isinstance (other , type (self )):
109140 return NotImplemented
110- return self .int >= other .int
141+ return self ._str >= other ._str
111142
112143 def __lt__ (self , other ):
113144 if not isinstance (other , type (self )):
114145 return NotImplemented
115- return self .int < other .int
146+ return self ._str < other ._str
116147
117148 def new (self , * args , ** kw ):
118149 return type (self )(* args , ** kw , max_len = self ._max_len )
0 commit comments