예제 #1
0
def wizard_ranges(launch_date_unrounded):
    """
    Return the active_when ranges to be used by the wizard

    Returns (active_all, active_call_text, active_forward_to) where:

     - active_forward_text runs from 8am on launch day, or 3 hours before the
       launch (whichever is earlier), until 3 hours after the launch
     - active_call_text runs from midnight 3 days in advance (round down to
       midnight) until active_forward_text starts
     - active_all covers both

    Lower bounds are rounded down, and upper bounds up, to whole hours.
    """

    hours = lambda n: datetime.timedelta(hours=n)

    launch_date = launch_date_unrounded \
                  .replace(minute=0, second=0, microsecond=0)

    start_forward_to = min(launch_date - hours(3), launch_date.replace(hour=8))

    end_forward_to = launch_date + hours(3)
    if launch_date != launch_date_unrounded:
        end_forward_to += hours(1)  # round up

    start_call_text = launch_date.replace(hour=0) - datetime.timedelta(days=3)

    return (DateTimeRange(start_call_text, end_forward_to, bounds='[)'),
            DateTimeRange(start_call_text, start_forward_to, bounds='[)'),
            DateTimeRange(start_forward_to, end_forward_to, bounds='[)'))
예제 #2
0
파일: test_apps.py 프로젝트: tnir/django
    def test_register_serializer_for_migrations(self):
        tests = (
            (DateRange(empty=True), DateRangeField),
            (DateTimeRange(empty=True), DateRangeField),
            (DateTimeTZRange(None, None, '[]'), DateTimeRangeField),
            (NumericRange(Decimal('1.0'), Decimal('5.0'), '()'), DecimalRangeField),
            (NumericRange(1, 10), IntegerRangeField),
        )

        def assertNotSerializable():
            for default, test_field in tests:
                with self.subTest(default=default):
                    field = test_field(default=default)
                    with self.assertRaisesMessage(ValueError, 'Cannot serialize: %s' % default.__class__.__name__):
                        MigrationWriter.serialize(field)

        assertNotSerializable()
        with self.modify_settings(INSTALLED_APPS={'append': 'django.contrib.postgres'}):
            for default, test_field in tests:
                with self.subTest(default=default):
                    field = test_field(default=default)
                    serialized_field, imports = MigrationWriter.serialize(field)
                    self.assertEqual(imports, {
                        'import django.contrib.postgres.fields.ranges',
                        'import psycopg2.extras',
                    })
                    self.assertIn(
                        '%s.%s(default=psycopg2.extras.%r)' % (
                            field.__module__,
                            field.__class__.__name__,
                            default,
                        ),
                        serialized_field
                    )
        assertNotSerializable()
예제 #3
0
def get_date_time_range(date_string, schedule_string, duration_string):
    # DETERMINE DAY MONTH YEAR
    match = re.match(from_to_regex, date_string)
    if match is not None:
        matches = match.group(1, 2, 3, 4)
        if all(matches):
            month = matches[2]
            year = matches[3]
            day_strings = [
                year + '-' +
                parse_datetime(month, date_formats=['%B']).strftime('%m') +
                '-' + str(day)
                for day in range(int(matches[0]), int(matches[1]))
            ]
    else:
        day_string = parse_datetime(date_string, date_formats=['%E %dd %B %Y'])
        if day_string is not None:
            day_strings = [day_string.strftime(DAY_FORMAT)]
    # DETERMINE START AND END SCHEDULE
    end_hour_string = None
    if 'et' in schedule_string:
        return [DateTimeRange()]
    if '-' in schedule_string:
        (start_hour_string, end_hour_string) = schedule_string.split('-')
        format_end_hour_string = get_format_timedelta_string(end_hour_string)
    else:
        start_hour_string = schedule_string
    format_start_hour_string = get_format_timedelta_string(start_hour_string)
    # DETERMINE DURATION
    duration = parse_timedelta(duration_string)
    # CONCAT
    date_time_ranges = [None] * (len(day_strings))
    for (index, day_string) in list(enumerate(day_strings)):
        start_date_string = day_string + 'T' + format_start_hour_string + 'Z'
        start_date = read_date(start_date_string)
        if end_hour_string is not None:
            end_date_string = day_string + 'T' + format_end_hour_string + 'Z'
            end_date = read_date(end_date_string)
        else:
            end_date = start_date + duration
        date_time_ranges[index] = DateTimeRange(start_date, end_date)
    # RETURN
    return date_time_ranges
예제 #4
0
def parse_message_edit_form():
    """
    Parse message_edit.html's form from request.form into a message dict

    Tolerates:
     - active_when missing: ignored (the active_when key is ommitted)

    Parse failure actions:
     - forward_to integer parsing fails: 400 Bad Request (from intbrq)
     - datetime parse failure: Store active_when as a dict
       (rather than DateTimeRange) in form
       {"lower": string, "upper": string} for repopulating the form
       (attributes vs items is not an issue for jinja2);
       set message["active_when_invalid"] to true.

    It's up to the caller to check call_text xor forward_to,
    whether "active_when" is present, and whether active_when_invalid is
    set, as appropriate.
    """

    message = {}

    for key in ("short_name", "web_short_text", "web_long_text", "call_text",
                "forward_to"):
        message[key] = request.form[key]

    if message["call_text"] == "":
        message["call_text"] = None

    if message["forward_to"] == "":
        message["forward_to"] = None
    else:
        message["forward_to"] = intbrq(message["forward_to"])

    try:
        lower = parse_datetime(request.form["active_when_lower"])
        upper = parse_datetime(request.form["active_when_upper"])
        if lower >= upper:
            raise ValueError
    except KeyError:
        pass
    except ValueError:
        # Note that we could produce a KeyError here if _lower is present
        # but _upper is not. This is not an issue, since a client sending
        # only is clearly a bad client and deserves the HTTP 400 it will get.
        message["active_when"] = {
            "lower": request.form["active_when_lower"],
            "upper": request.form["active_when_upper"]
        }
        message["active_when_invalid"] = True
    else:
        message["active_when"] = DateTimeRange(lower, upper, bounds='[)')

    return message
예제 #5
0
 def __init__(self, **kw):
     value_from = kw.pop('value_from', None)
     value_to = kw.pop('value_to', None)
     if value_from or value_to:
         if 'period' in kw:
             raise TypeError(
                 'period not allowed if value_from or value_to used')
         period = DateTimeRange(value_from, value_to)
     else:
         period = kw.pop('period', None)
     super(Temporal, self).__init__(period=period, **kw)
    def test_write_tsrange(self):
        test_value = DateTimeRange(datetime.datetime(2014, 6, 8, 12, 12, 45), datetime.datetime(2016, 7, 6, 14, 12, 8))
        test_columns_info = []
        col = DbColumn()
        col.data_type = datatypes.DATATYPE_TSRANGE
        test_columns_info.append(col)
        mock_storage_data_reader = MockStorageDataReader(self._cursor, test_columns_info)
        mock_storage_data_reader.get_value = mock.MagicMock(return_value=test_value)

        res = self._writer.write_row(mock_storage_data_reader)
        self.assertEqual(self.get_expected_length_with_additional_buffer_for_size(len("[2014-06-08T12:12:45,2016-07-06T14:12:08)")), res)
예제 #7
0
def write_nap(cur, guard_id, nap_start, nap_end):
    during = DateTimeRange(lower=nap_start, upper=nap_end, bounds="[)")
    cur.execute(
        """
        insert into naps
        (guard_id, during)
        values
        (%s, %s)
        """,
        (guard_id, during),
    )
    global WROTE
    WROTE += 1
예제 #8
0
def default_active_when():
    """
    Return a default DateTimeRange to popualate new message row forms

    The lower bound is tomorrow at midnight, the upper is the midnight after.
    """

    today = datetime.datetime.now() \
            .replace(hour=0, minute=0, second=0, microsecond=0)
    days = lambda n: datetime.timedelta(days=n)
    lower = today + days(1)
    upper = today + days(2)
    return DateTimeRange(lower, upper, bounds='[)')
예제 #9
0
def _apply_time_range_filters(query, start_time, end_time):
    if type(start_time) is date:
        start_time = datetime(start_time.year, start_time.month,
                              start_time.day)
    if type(end_time) is date:
        end_time = datetime(end_time.year, end_time.month, end_time.day, 23,
                            59, 59)
    if start_time or end_time:
        return query.filter(
            func.tsrange(Activity.start_time, Activity.end_time,
                         "[]").op("&&")(DateTimeRange(start_time, end_time,
                                                      "[)")))

    return query
예제 #10
0
def parse_datetimerange(s):

    tok = Token(s)
    t, x = tok.next()
    if t != 'b_bound':
        raise ParseError("Expected %s in the beginning; found '%s'" %
                         (tuple2str(B_BOUND), x))

    bounds = x

    t, x = tok.next()
    if t not in ('delim', 'datetime'):
        raise ParseError(
            "Expected datetime string or ',' after '%s'; found '%s'" %
            (bounds, x))

    if t == 'datetime':
        t1 = parse_datetime(x)
        t, x = tok.next()
        if t != 'delim':
            raise ParseError(
                "Expected ',' after first datetime string; found '%s'" % x)
    else:
        t1 = None

    t, x = tok.next()
    if t not in ('datetime', 'e_bound'):
        raise ParseError(
            "Expected datetime string or %s after ','; found '%s'" %
            (tuple2str(E_BOUND), x))

    if t == 'datetime':
        t2 = parse_datetime(x)
        t, x = tok.next()
    else:
        t2 = None

    if t != 'e_bound':
        raise ParseError("Expected %s at the end" % tuple2str(E_BOUND))

    bounds += x

    return DateTimeRange(t1, t2, bounds)
예제 #11
0
    def test_register_serializer_for_migrations(self):
        tests = (
            (DateRange(empty=True), DateRangeField),
            (DateTimeRange(empty=True), DateRangeField),
            (DateTimeTZRange(None, None, "[]"), DateTimeRangeField),
            (NumericRange(Decimal("1.0"), Decimal("5.0"),
                          "()"), DecimalRangeField),
            (NumericRange(1, 10), IntegerRangeField),
        )

        def assertNotSerializable():
            for default, test_field in tests:
                with self.subTest(default=default):
                    field = test_field(default=default)
                    with self.assertRaisesMessage(
                            ValueError, "Cannot serialize: %s" %
                            default.__class__.__name__):
                        MigrationWriter.serialize(field)

        assertNotSerializable()
        with self.modify_settings(
                INSTALLED_APPS={"append": "django.contrib.postgres"}):
            for default, test_field in tests:
                with self.subTest(default=default):
                    field = test_field(default=default)
                    serialized_field, imports = MigrationWriter.serialize(
                        field)
                    self.assertEqual(
                        imports,
                        {
                            "import django.contrib.postgres.fields.ranges",
                            "import psycopg2.extras",
                        },
                    )
                    self.assertIn(
                        "%s.%s(default=psycopg2.extras.%r)" % (
                            field.__module__,
                            field.__class__.__name__,
                            default,
                        ),
                        serialized_field,
                    )
        assertNotSerializable()
예제 #12
0
 def _normalize_coerce_tsrange(self, value):
     datetimes = map(
         lambda x: datetime.datetime.strptime(x, '%Y-%m-%d %H:%M:%S'),
         value)
     return DateTimeRange(*datetimes)
예제 #13
0
 def value_to(self, timestamp):
     if self.period is None:
         lower = None
     else:
         lower = self.period.lower
     self.period = DateTimeRange(lower, timestamp)
예제 #14
0
 def process(value):
     if value:
         return DateTimeRange(value[0], value[1])
 def test_normalise_hypothesis_tsrange(self, a):
     a = DateTimeRange(*a)
     cursor = connection.cursor()
     cursor.execute("SELECT %s::tsrange", [a])
     self.assertEqual(cursor.fetchone()[0], normalise(a), a)
 def test_with_hypothesis_datetimes(self, a, b):
     a = DateTimeRange(*a)
     b = DateTimeRange(*b)
     cursor = connection.cursor()
     cursor.execute("SELECT %s::tsrange && %s::tsrange", [a, b])
     self.assertEqual(cursor.fetchone()[0], a & b, "{} && {}".format(a, b))
예제 #17
0
class TestTableTypes(TrackedTable):
    name = 'test_table_types'
    default_values = OrderedDict([
        ('test_table_types_bool', True),
        ('test_table_types_real', 9.99),
        ('test_table_types_double', 9.99),
        ('test_table_types_smallint', 9),
        ('test_table_types_integer', 50000),
        ('test_table_types_bigint', 5000000000),
        ('test_table_types_numeric', Decimal('1.1')),
        ('test_table_types_varchar', 'hi there'),
        ('test_table_types_text', 'hi there'),
        ('test_table_types_bytea', b'hi there'),
        ('test_table_types_date', date(year=1991, month=11, day=11)),
        ('test_table_types_time', time(hour=11, minute=39, second=22)),
        ('test_table_types_timetz', time(hour=11, minute=39, second=22, tzinfo=pytz.utc)),
        ('test_table_types_timestamp', datetime(year=1991, month=11, day=11, hour=11, minute=39, second=22)),
        ('test_table_types_timestamptz', datetime(year=1991, month=11, day=11, hour=11, minute=39, second=22, tzinfo=pytz.utc)),
        ('test_table_types_interval', timedelta(hours=15)),
        ('test_table_types_array', ['a', 'b', 'c', 'd', 'e']),
        # ('test_table_types_hstore', {'a': 1, 'b': 2, 'c': 3}), this dict would be passed to test_table_types_hstore
        ('test_table_types_int4range', NumericRange(lower=1, upper=10)),
        ('test_table_types_int8range', NumericRange(lower=1, upper=50000)),
        ('test_table_types_numrange', NumericRange(lower=Decimal('0.1'), upper=Decimal('1.1'))),
        ('test_table_types_daterange', DateRange(
            lower=date(year=1991, month=11, day=11),
            upper=date(year=1991, month=11, day=21),
        )),
        ('test_table_types_tsrange', DateTimeRange(
            lower=datetime(year=1991, month=11, day=11, hour=11, minute=39, second=22),
            upper=datetime(year=1991, month=11, day=21, hour=11, minute=39, second=22),
        )),
        ('test_table_types_tstzrange', DateTimeTZRange(
            lower=datetime(year=1991, month=11, day=11, hour=11, minute=39, second=22, tzinfo=pytz.utc),
            upper=datetime(year=1991, month=11, day=21, hour=11, minute=39, second=22, tzinfo=pytz.utc),
        )),
        # ('test_table_types_uuid', UUID(bytes=b'1234567890123456')),
        # ('test_table_types_inet', ip_network('192.168.0.0')),
        # ('test_table_types_cidr', ip_network('192.168.0.0')),
        ('test_table_types_json', json.dumps(['a', {'b': 2}, 2])),
        ('test_table_types_jsonb', json.dumps(['a', {'b': 2}, 2])),
    ])

    def build(self, cursor=None):
        if not cursor:
            cursor = self.get_cursor()

        cursor.execute(
            "CREATE TABLE test_table_types ("
                "test_table_types_bool bool DEFAULT %s, "
                "test_table_types_real real DEFAULT %s, "
                "test_table_types_double double precision DEFAULT %s, "
                "test_table_types_smallint smallint DEFAULT %s, "
                "test_table_types_integer integer DEFAULT %s, "
                "test_table_types_bigint bigint DEFAULT %s, "
                "test_table_types_numeric numeric DEFAULT %s, "
                "test_table_types_varchar varchar DEFAULT %s, "
                "test_table_types_text text DEFAULT %s, "
                "test_table_types_bytea bytea DEFAULT %s, "
                "test_table_types_date date DEFAULT %s, "
                "test_table_types_time time DEFAULT %s, "
                "test_table_types_timetz timetz DEFAULT %s, "
                "test_table_types_timestamp timestamp DEFAULT %s, "
                "test_table_types_timestamptz timestamptz DEFAULT %s, "
                "test_table_types_interval interval DEFAULT %s, "
                "test_table_types_array text[] DEFAULT %s, "
                # "test_table_types_hstore hstore DEFAULT %s, " hstore is unused.
                "test_table_types_int4range int4range DEFAULT %s, "
                "test_table_types_int8range int8range DEFAULT %s, "
                "test_table_types_numrange numrange DEFAULT %s, "
                "test_table_types_daterange daterange DEFAULT %s, "
                "test_table_types_tsrange tsrange DEFAULT %s, "
                "test_table_types_tstzrange tstzrange DEFAULT %s, "
                # "test_table_types_uuid uuid DEFAULT %s, " uuid is unused.
                # "test_table_types_inet inet DEFAULT %s, " inet types are unused.
                # "test_table_types_cidr cidr DEFAULT %s, "
                "test_table_types_json json DEFAULT %s, "
                "test_table_types_jsonb jsonb DEFAULT %s "
            ")", list(self.default_values.values())
        )

        for i in range(1000):
            cursor.execute("INSERT INTO test_table_types DEFAULT VALUES")
예제 #18
0
 def value_from(self, timestamp):
     if self.period is None:
         upper = None
     else:
         upper = self.period.upper
     self.period = DateTimeRange(timestamp, upper)