diff --git a/relational/rtypes.py b/relational/rtypes.py index 1bc4970..419f2f5 100644 --- a/relational/rtypes.py +++ b/relational/rtypes.py @@ -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})$' ) - - def autocast(self) -> Union[int, float, 'Rdate', 'Rstring']: - ''' - Returns the automatic cast for this - value. - ''' - try: - return self._autocast - except: - 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: - 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 +CastValue = Union[str, int, float, 'Rdate'] -class Rdate (object): +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) + try: + int(value) + r.add(int) + except ValueError: + pass + + try: + float(value) + r.add(float) + except ValueError: + pass + return r + + +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):