Ejemplo n.º 1
0
 def test_valid(self):
     ref = time.mktime(time.strptime("2004", "%Y"))
     self.assertEqual(util.parse_date("2004"), ref)
     self.assertEqual(util.parse_date("2004-01-01"), ref)
     self.assertEqual(util.parse_date("2004-1-1"), ref)
     self.assertTrue(
         util.parse_date("2004-01-01") < util.parse_date("2004-01-02"))
Ejemplo n.º 2
0
 def test_date_op(self):
     o, v = map_numeric_op("lastplayed", "=", "2004")
     self.assertTrue(o(parse_date("2004"), v))
     o, v = map_numeric_op("lastplayed", "<", "2004")
     self.assertTrue(o(parse_date("2003"), v))
     o, v = map_numeric_op("lastplayed", ">", "2004")
     self.assertFalse(o(parse_date("2003"), v))
Ejemplo n.º 3
0
 def test_valid(self):
     ref = time.mktime(time.strptime("2004", "%Y"))
     self.assertEqual(util.parse_date("2004"), ref)
     self.assertEqual(util.parse_date("2004-01-01"), ref)
     self.assertEqual(util.parse_date("2004-1-1"), ref)
     self.assertTrue(
         util.parse_date("2004-01-01") < util.parse_date("2004-01-02"))
Ejemplo n.º 4
0
 def test_date_op(self):
     o, v = map_numeric_op("lastplayed", "=", "2004")
     self.assertTrue(o(parse_date("2004"), v))
     o, v = map_numeric_op("lastplayed", "<", "2004")
     self.assertTrue(o(parse_date("2003"), v))
     o, v = map_numeric_op("lastplayed", ">", "2004")
     self.assertFalse(o(parse_date("2003"), v))
Ejemplo n.º 5
0
 def test_date_tag(self):
     song = AudioFile({'date': '2012-11-09'})
     self.failUnless(NumexprTag('date').evaluate(song, 0, True)
                     == parse_date('2012-11-09'))
     self.failUnless(NumexprTag('date').evaluate(song, 424242, True)
                     == parse_date('2012-11-09'))
     self.failUnless(NumexprTag('date').evaluate(song, 0, True)
                     > parse_date('2012-11-08'))
     self.failUnless(NumexprTag('date').evaluate(song, 0, True)
                     < parse_date('2012-11-10'))
Ejemplo n.º 6
0
 def test_date_tag(self):
     song = AudioFile({'date': '2012-11-09'})
     self.failUnless(NumexprTag('date').evaluate(song, 0, True)
                     == parse_date('2012-11-09'))
     self.failUnless(NumexprTag('date').evaluate(song, 424242, True)
                     == parse_date('2012-11-09'))
     self.failUnless(NumexprTag('date').evaluate(song, 0, True)
                     > parse_date('2012-11-08'))
     self.failUnless(NumexprTag('date').evaluate(song, 0, True)
                     < parse_date('2012-11-10'))
Ejemplo n.º 7
0
 def __init__(self, date):
     self.date = parse_date(date)
     parts = date.split('-')
     self.number = int(parts[0])
     if len(parts) > 1:
         self.number -= int(parts[1])
     if len(parts) > 2:
         self.number -= int(parts[2])
Ejemplo n.º 8
0
 def evaluate(self, data, time, use_date):
     if self.__tag == 'date':
         date = data('date')
         if not date:
             return None
         try:
             num = parse_date(date)
         except ValueError:
             return None
     else:
         num = data(self.__ftag, None)
     if num is not None:
         if self.__tag in TIME_KEYS:
             num = time - num
         return round(num, 2)
     return None
Ejemplo n.º 9
0
 def evaluate(self, data, time, use_date):
     if self._tag == 'date':
         date = data('date')
         if not date:
             return None
         try:
             num = parse_date(date)
         except ValueError:
             return None
     else:
         num = data(self._ftag, None)
     if num is not None:
         if self._ftag in TIME_TAGS:
             num = time - num
         return round(num, 2)
     return None
Ejemplo n.º 10
0
 def evaluate(self, data, time, use_date):
     if self._tag == 'date':
         date = data('date')
         if not date:
             return None
         try:
             num = parse_date(date)
         except ValueError:
             return None
     else:
         num = data(self._ftag, None)
     if num is not None:
         # Strip aggregate function from tag
         func_start = self._ftag.find(":")
         tag = self._ftag[:func_start] if func_start >= 0 else self._ftag
         if tag in TIME_TAGS:
             num = time - num
         return round(num, 2)
     return None
Ejemplo n.º 11
0
def map_numeric_op(tag, op, value, time_=None):
    """Maps a human readable numeric comparison to something we can use.

    Handles cases like '< 3 days', '>5MB' etc..
    If parsing fails, raises a ParseError.

    Takes a tag, an operator string and and a value string:
        op, v = map_numeric_op("added", "<", "today")

    Returns an (operator function, numeric value) tuple:
        if op(v, song("~#added")): ...

    (time_ is only used for testing)

    """

    operators = {
        "<": operator.lt,
        "<=": operator.le,
        ">": operator.gt,
        ">=": operator.ge,
        "=": operator.eq,
        "!=": operator.ne,
    }

    if op not in operators:
        raise ParseError("Unknown operator %s" % op)

    inv_op = op.replace(">", "<") if op[0] == ">" else op.replace("<", ">")
    inv_op = operators[inv_op]
    op = operators[op]

    value = value.lower().strip()

    if tag == "date":
        if not validate_query_date(value):
            raise ParseError("Invalid date %r" % value)
        return (op, date_key(value))

    if tag in TIME_KEYS:
        try:
            value = parse_date(value)
        except ValueError:
            pass
        else:
            return (op, value)

        if value == "now":
            value = (time_ or time.time())
            return (inv_op, value)
        if value == "today":
            value = (time_ or time.time()) - 24 * 60 * 60
            return (inv_op, value)

    # check for time formats: "5:30"
    # TODO: handle "5:30 ago"
    try:
        hms = map(int, value.split(":"))
    except ValueError:
        pass
    else:
        if len(hms) > 1:
            value = 0
            for t in hms:
                value *= 60
                value += t
            if tag in TIME_KEYS:
                value = (time_ or time.time()) - value
                return (inv_op, value)
            return (op, value)

    # get the biggest float/int
    max_val = ""
    for i in xrange(len(value) + 1, 0, -1):
        part = value[:i]
        try:
            float(part)
        except ValueError:
            pass
        else:
            max_val = part
            break
    else:
        raise ParseError("No numeric value %r" % value)

    unit = value[len(max_val):].strip()

    try:
        value = int(max_val)
    except ValueError:
        value = float(max_val)

    if tag in TIME_KEYS:
        part = (unit.split() or [""])[0].rstrip("s")
        if part.startswith("second"):
            value = value
        elif part == "minute":
            value *= 60
        elif part == "hour":
            value *= 60 * 60
        elif part == "day":
            value *= 24 * 60 * 60
        elif part == "week":
            value *= 7 * 24 * 60 * 60
        elif part == "month":
            value *= 30 * 24 * 60 * 60
        elif part == "year":
            value *= 365 * 24 * 60 * 60
        elif unit:
            raise ParseError("No time unit: %r" % unit)
        else:
            # don't allow raw seconds since epoch. It's not that usefull
            # and overlaps with the date parsing
            # (10 would be 10 seconds, 1970 would be 0)
            raise ParseError("No valid time format")
        value = int((time_ or time.time()) - value)
        return (inv_op, value)

    if tag in SIZE_KEYS:
        if unit.startswith("g"):
            value *= 1024**3
        elif unit.startswith("m"):
            value *= 1024**2
        elif unit.startswith("k"):
            value *= 1024
        elif unit.startswith("b"):
            pass
        elif unit:
            raise ParseError("No size unit: %r" % unit)
    elif unit:
        raise ParseError("Tag %r does not support units (%r)" % (tag, unit))

    return (op, value)
Ejemplo n.º 12
0
def map_numeric_op(tag, op, value, time_=None):
    """Maps a human readable numeric comparison to something we can use.

    Handles cases like '< 3 days', '>5MB' etc..
    If parsing fails, raises a ParseError.

    Takes a tag, an operator string and and a value string:
        op, v = map_numeric_op("added", "<", "today")

    Returns an (operator function, numeric value) tuple:
        if op(v, song("~#added")): ...

    (time_ is only used for testing)

    """

    operators = {
        "<": operator.lt,
        "<=": operator.le,
        ">": operator.gt,
        ">=": operator.ge,
        "=": operator.eq,
        "!=": operator.ne,
    }

    if op not in operators:
        raise ParseError("Unknown operator %s" % op)

    inv_op = op.replace(">", "<") if op[0] == ">" else op.replace("<", ">")
    inv_op = operators[inv_op]
    op = operators[op]

    value = value.lower().strip()

    if tag == "date":
        if not validate_query_date(value):
            raise ParseError("Invalid date %r" % value)
        return (op, date_key(value))

    if tag in TIME_KEYS:
        try:
            value = parse_date(value)
        except ValueError:
            pass
        else:
            return (op, value)

        if value == "now":
            value = (time_ or time.time())
            return (inv_op, value)
        if value == "today":
            value = (time_ or time.time()) - 24 * 60 * 60
            return (inv_op, value)

    # check for time formats: "5:30"
    # TODO: handle "5:30 ago"
    try:
        hms = map(int, value.split(":"))
    except ValueError:
        pass
    else:
        if len(hms) > 1:
            value = 0
            for t in hms:
                value *= 60
                value += t
            if tag in TIME_KEYS:
                value = (time_ or time.time()) - value
                return (inv_op, value)
            return (op, value)

    # get the biggest float/int
    max_val = ""
    for i in xrange(len(value) + 1, 1, -1):
        part = value[:i]
        try:
            float(part)
        except ValueError:
            pass
        else:
            max_val = part
            break
    else:
        raise ParseError("No numeric value %r" % value)

    unit = value[len(max_val):].strip()

    try:
        value = int(max_val)
    except ValueError:
        value = float(max_val)

    if tag in TIME_KEYS:
        part = (unit.split() or [""])[0].rstrip("s")
        if part.startswith("second"):
            value = value
        elif part == "minute":
            value *= 60
        elif part == "hour":
            value *= 60 * 60
        elif part == "day":
            value *= 24 * 60 * 60
        elif part == "week":
            value *= 7 * 24 * 60 * 60
        elif part == "month":
            value *= 30 * 24 * 60 * 60
        elif part == "year":
            value *= 365 * 24 * 60 * 60
        elif unit:
            raise ParseError("No time unit: %r" % unit)
        else:
            # don't allow raw seconds since epoch. It's not that usefull
            # and overlaps with the date parsing
            # (10 would be 10 seconds, 1970 would be 0)
            raise ParseError("No valid time format")
        value = int((time_ or time.time()) - value)
        return (inv_op, value)

    if tag in SIZE_KEYS:
        if unit.startswith("g"):
            value *= 1024 ** 3
        elif unit.startswith("m"):
            value *= 1024 ** 2
        elif unit.startswith("k"):
            value *= 1024
        elif unit.startswith("b"):
            pass
        elif unit:
            raise ParseError("No size unit: %r" % unit)
    elif unit:
        raise ParseError("Tag %r does not support units (%r)" % (tag, unit))

    return (op, value)