New code to guess types

master
Salvo 'LtWorf' Tomaselli 2020-08-19 08:12:56 +07:00
parent f410b112af
commit 73aa0dd2a1
No known key found for this signature in database
GPG Key ID: B3A7CF0C801886CF
1 changed files with 34 additions and 85 deletions

@ -23,98 +23,47 @@
import datetime
import keyword
import re
from typing import Union
from typing import Union, Set, Any, Callable
RELATION_NAME_REGEXP = re.compile(r'^[_a-z][_a-z0-9]*$', re.IGNORECASE)
class Rstring(str):
'''String subclass with some custom methods'''
int_regexp = re.compile(r'^[\+\-]{0,1}[0-9]+$')
float_regexp = re.compile(r'^[\+\-]{0,1}[0-9]+(\.([0-9])+)?$')
date_regexp = re.compile(
_date_regexp = re.compile(
r'^([0-9]{1,4})(\\|-|/)([0-9]{1,2})(\\|-|/)([0-9]{1,2})$'
)
CastValue = Union[str, int, float, 'Rdate']
def guess_type(value: str) -> Set[Callable[[Any], Any]]:
r: Set[Callable[[Any], Any]] = {str}
if _date_regexp.match(value) is not None:
r.add(Rdate)
def autocast(self) -> Union[int, float, 'Rdate', 'Rstring']:
'''
Returns the automatic cast for this
value.
'''
try:
return self._autocast
except:
int(value)
r.add(int)
except ValueError:
pass
self._autocast = self # type: Union[int, float, 'Rdate', 'Rstring']
if len(self) > 0:
if self.isInt():
self._autocast = int(self)
elif self.isFloat():
self._autocast = float(self)
elif self.isDate():
self._autocast = Rdate(self)
return self._autocast
def isInt(self) -> bool:
'''Returns true if the string represents an int number
it only considers as int numbers the strings matching
the following regexp:
r'^[\+\-]{0,1}[0-9]+$'
'''
return Rstring.int_regexp.match(self) is not None
def isFloat(self) -> bool:
'''Returns true if the string represents a float number
it only considers as float numbers, the strings matching
the following regexp:
r'^[\+\-]{0,1}[0-9]+(\.([0-9])+)?$'
'''
return Rstring.float_regexp.match(self) is not None
def isDate(self) -> bool:
'''Returns true if the string represents a date,
in the format YYYY-MM-DD. as separators '-' , '\', '/' are allowed.
As side-effect, the date object will be stored for future usage, so
no more parsings are needed
'''
try:
return self._isdate # type: ignore
except:
float(value)
r.add(float)
except ValueError:
pass
r = Rstring.date_regexp.match(self)
if r is None:
self._isdate = False
self._date = None
return False
try: # Any of the following operations can generate an exception, if it happens, we aren't dealing with a date
year = int(r.group(1))
month = int(r.group(3))
day = int(r.group(5))
d = datetime.date(year, month, day)
self._isdate = True
self._date = d
return True
except:
self._isdate = False
self._date = None
return False
def getDate(self):
'''Returns the datetime.date object or None'''
try:
return self._date
except:
self.isDate()
return self._date
return r
class Rdate (object):
def cast(value: str, guesses: Set) -> CastValue:
if int in guesses:
return int(value)
if Rdate in guesses:
print(repr(value), guesses)
return Rdate(value)
if float in guesses:
return float(value)
return value
class Rdate(datetime.date):
'''Represents a date'''
def __init__(self, date):