|
|
|
@ -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):
|
|
|
|
|