Beispiel #1
0
    def test_croniter_range_derived_class(self):
        # trivial example extending croniter

        class croniter_nosec(croniter):
            """ Like croniter, but it forbids second-level cron expressions. """
            @classmethod
            def expand(cls, expr_format, *args, **kwargs):
                if len(expr_format.split()) == 6:
                    raise CroniterBadCronError(
                        "Expected 'min hour day mon dow'")
                return croniter.expand(expr_format, *args, **kwargs)

        cron = "0 13 8 1,4,7,10 wed"
        matches = list(
            croniter_range(datetime(2020, 1, 1),
                           datetime(2020, 12, 31),
                           cron,
                           day_or=False,
                           _croniter=croniter_nosec))
        self.assertEqual(len(matches), 3)

        cron = "0 1 8 1,15,L wed 15,45"
        with self.assertRaises(CroniterBadCronError):
            # Should fail using the custom class that forbids the seconds expression
            croniter_nosec(cron)

        with self.assertRaises(CroniterBadCronError):
            # Should similarly fail because the custom class rejects seconds expr
            i = croniter_range(datetime(2020, 1, 1),
                               datetime(2020, 12, 31),
                               cron,
                               _croniter=croniter_nosec)
            next(i)
Beispiel #2
0
 def test_input_type_exceptions(self):
     dt_start1 = datetime(2019, 1, 1)
     dt_stop1 = datetime(2020, 1, 1)
     f_start1 = 1552252218.0
     f_stop1 = 1591823311.0
     # Mix start/stop types
     with self.assertRaises(TypeError):
         list(croniter_range(dt_start1, f_stop1, "0 * * * *"), ret_type=datetime)
     with self.assertRaises(TypeError):
         list(croniter_range(f_start1, dt_stop1, "0 * * * *"))
Beispiel #3
0
    def test_issue145_range(self):
        cron = "0 13 8 1,4,7,10 wed"
        matches = list(croniter_range(datetime(2020, 1, 1), datetime(2020, 12, 31), cron, day_or=False))
        self.assertEqual(len(matches), 3)
        self.assertEqual(matches[0], datetime(2020, 1, 8, 13))
        self.assertEqual(matches[1], datetime(2020, 4, 8, 13))
        self.assertEqual(matches[2], datetime(2020, 7, 8, 13))

        # No matches within this range; therefore expect empty list
        matches = list(croniter_range(datetime(2020, 9, 30), datetime(2020, 10, 30), cron, day_or=False))
        self.assertEqual(len(matches), 0)
Beispiel #4
0
 def test_1day_step_no_ends(self):
     # Test without ends (exclusive)
     start = datetime(2016, 12, 2)
     stop = datetime(2016, 12, 10)
     fwd = list(croniter_range(start, stop, '0 0 * * *', exclude_ends=True))
     self.assertEqual(len(fwd), 7)
     self.assertNotEqual(fwd[0], start)
     self.assertNotEqual(fwd[-1], stop)
     # Test the same, but in reverse
     rev = list(croniter_range(stop, start, '0 0 * * *', exclude_ends=True))
     self.assertEqual(len(rev), 7)
     self.assertNotEqual(fwd[0], stop)
     self.assertNotEqual(fwd[-1], start)
Beispiel #5
0
 def test_1day_step(self):
     start = datetime(2016, 12, 2)
     stop = datetime(2016, 12, 10)
     fwd = list(croniter_range(start, stop, '0 0 * * *'))
     self.assertEqual(len(fwd), 9)
     self.assertEqual(fwd[0], start)
     self.assertEqual(fwd[-1], stop)
     # Test the same, but in reverse
     rev = list(croniter_range(stop, start, '0 0 * * *'))
     self.assertEqual(len(rev), 9)
     # Ensure forward/reverse are a mirror image
     rev.reverse()
     self.assertEqual(fwd, rev)
Beispiel #6
0
 def test_1minute_step_float(self):
     start = datetime(2000, 1, 1, 0, 0)
     stop = datetime(2000, 1, 1, 0, 1)
     res = list(croniter_range(start, stop, '* * * * *', ret_type=float))
     self.assertEqual(len(res), 2)
     self.assertEqual(res[0], 946684800.0)
     self.assertEqual(res[-1] - res[0], 60)
Beispiel #7
0
 def test_dt_types(self):
     start = mydatetime(2020, 9, 24)
     stop = datetime(2020, 9, 28)
     try:
         list(croniter_range(start, stop, '0 0 * * *'))
     except CroniterBadTypeRangeError:
         self.fail('should not be triggered')
Beispiel #8
0
def launch_scheduled_runs_for_schedule(instance,
                                       schedule_state,
                                       end_datetime_utc,
                                       max_catchup_runs,
                                       debug_crash_flags=None):
    check.inst_param(instance, "instance", DagsterInstance)
    check.inst_param(schedule_state, "schedule_state", ScheduleState)
    check.inst_param(end_datetime_utc, "end_datetime_utc", datetime.datetime)

    latest_tick = instance.get_latest_tick(schedule_state.schedule_origin_id)

    if not latest_tick:
        start_timestamp_utc = schedule_state.start_timestamp
    elif latest_tick.status == ScheduleTickStatus.STARTED:
        # Scheduler was interrupted while performing this tick, re-do it
        start_timestamp_utc = latest_tick.timestamp
    else:
        start_timestamp_utc = latest_tick.timestamp + 1

    start_datetime_utc = datetime.datetime.fromtimestamp(start_timestamp_utc,
                                                         tz=get_utc_timezone())

    tick_times = list(
        croniter_range(start_datetime_utc, end_datetime_utc,
                       schedule_state.cron_schedule))

    for schedule_time_utc in tick_times[-max_catchup_runs:]:
        if latest_tick and latest_tick.timestamp == schedule_time_utc.timestamp(
        ):
            tick = latest_tick

        else:
            tick = instance.create_schedule_tick(
                ScheduleTickData(
                    schedule_origin_id=schedule_state.schedule_origin_id,
                    schedule_name=schedule_state.name,
                    timestamp=schedule_time_utc.timestamp(),
                    cron_schedule=schedule_state.cron_schedule,
                    status=ScheduleTickStatus.STARTED,
                ))

            _check_for_debug_crash(debug_crash_flags, "TICK_CREATED")

        with ScheduleTickHolder(tick, instance) as tick_holder:

            _check_for_debug_crash(debug_crash_flags, "TICK_HELD")

            with RepositoryLocationHandle.create_from_repository_origin(
                    schedule_state.origin.repository_origin,
                    instance) as repo_location_handle:
                repo_location = RepositoryLocation.from_handle(
                    repo_location_handle)
                _schedule_run_at_time(
                    instance,
                    repo_location,
                    schedule_state,
                    schedule_time_utc,
                    tick_holder,
                    debug_crash_flags,
                )
Beispiel #9
0
 def test_timezone_dst(self):
     """ Test across DST transition, which technially is a timzone change. """
     tz = pytz.timezone("US/Eastern")
     start = tz.localize(datetime(2020, 10, 30))
     stop = tz.localize(datetime(2020, 11, 10))
     res = list(croniter_range(start, stop, '0 0 * * *'))
     self.assertNotEqual(res[0].tzinfo, res[-1].tzinfo)
     self.assertEqual(len(res), 12)
Beispiel #10
0
 def test_auto_ret_type(self):
     data = [
         (datetime(2019, 1, 1), datetime(2020, 1, 1), datetime),
         (1552252218.0, 1591823311.0, float),
     ]
     for start, stop, rtype in data:
         ret = list(croniter_range(start, stop, "0 0 * * *"))
         self.assertIsInstance(ret[0], rtype)
Beispiel #11
0
 def test_1month_step(self):
     start = datetime(1982, 1, 1)
     stop = datetime(1983, 12, 31)
     res = list(croniter_range(start, stop, '0 0 1 * *'))
     self.assertEqual(len(res), 24)
     self.assertEqual(res[0], start)
     self.assertEqual(res[5].day, 1)
     self.assertEqual(res[-1], datetime(1983, 12, 1))
Beispiel #12
0
    def analyze_video(self, file, start, end, increment, update_expression):
        result = {}

        # run ffmpeg.probe to get the frame rate and frame count
        videoInfo = utils.get_video_info(file)

        startFrame = utils.seconds_to_frames(start, videoInfo['fps'])
        videoInfo['frame_count'] = videoInfo[
            'frame_count'] - utils.seconds_to_frames(end, videoInfo['fps'])

        # print some initial information
        logging.info(f"Analyzing {file}")
        result['fps'] = videoInfo['fps']
        result['runtime'] = videoInfo['runtime'] / 60

        # video name, no ext
        video_name = os.path.splitext(os.path.basename(file))[0]
        result['file'] = video_name

        # check if we have a "save" file
        currentPosition = startFrame
        saveFile = utils.read_db(self.db, utils.DB_LAST_PLAYED_FILE)
        if (file == saveFile['file']):
            currentPosition = float(saveFile['pos'])

            if (currentPosition < startFrame):
                currentPosition = startFrame

        # find total time to play entire movie
        result['total_time_to_play'] = self.time_to_play(
            videoInfo['frame_count'] - startFrame, float(increment),
            update_expression)

        # find time to play what's left
        result['remaining_time_to_play'] = self.time_to_play(
            videoInfo['frame_count'] - currentPosition, float(increment),
            update_expression)

        # figure out how many 'real time' minutes per hour
        now = datetime.now()
        tomorrow = now + timedelta(days=1)
        day_total = 0
        for i in croniter_range(now, tomorrow, update_expression):
            day_total = day_total + 1
        secondsPerIncrement = utils.frames_to_seconds(increment,
                                                      videoInfo['fps'])
        # this is how many "seconds" of film actually shown per second of realtime
        framesPerSecond = secondsPerIncrement / (60 / (day_total / 24) * 60)

        minutesPerHour = (framesPerSecond * 60)
        result['minutes_per_hour'] = minutesPerHour
        result['minutes_per_day'] = minutesPerHour * 24

        # number of frames left to play
        result['frames_left'] = videoInfo['frame_count'] - currentPosition

        return result
Beispiel #13
0
    def test_extra_hour_day_prio(self):
        def datetime_tz(*args, **kw):
            """ Defined this in another branch.  single-use-version """
            tzinfo = kw.pop("tzinfo")
            return tzinfo.localize(datetime(*args))

        tz = pytz.timezone("US/Eastern")
        cron = "0 3 * * *"
        start = datetime_tz(2020, 3, 7, tzinfo=tz)
        end = datetime_tz(2020, 3, 11, tzinfo=tz)
        ret = [i.isoformat() for i in croniter_range(start, end, cron)]
        self.assertEqual(ret, [
            "2020-03-07T03:00:00-05:00", "2020-03-08T03:00:00-04:00",
            "2020-03-09T03:00:00-04:00", "2020-03-10T03:00:00-04:00"
        ])
    def execute(self):
        """Execute the schedule.

        A check is done to make sure the schedule wasn't checked by another worker in the mean time.

        The task may be added several times if catch_up is True.

        Returns True if at least one task was queued (so you can loop for testing).
        """

        last_check = self.last_check
        self.refresh_from_db()
        if last_check != self.last_check:
            # this schedule was executed from another worker in the mean time
            return True

        # we update last_check already to reduce race condition chance
        self.last_check = timezone.now()
        self.save()

        did_something = False

        if last_check is None:
            next_dues = [croniter(self.cron, timezone.now()).get_prev(datetime)]
        else:
            next_dues = list(croniter_range(last_check, timezone.now(), self.cron))
            if not self.catch_up and len(next_dues) > 1:
                next_dues = [next_dues[-1]]

        for next_due in next_dues:

            logger.debug(f"Due : {self}")

            dt_kwarg = {}
            if self.datetime_kwarg:
                dt_kwarg = {self.datetime_kwarg: next_due}

            t = tasks[self.function].queue(*self.args, **self.kwargs, **dt_kwarg)
            if t:
                self.last_run = t
                self.save()

            did_something = True

        return did_something
Beispiel #15
0
def launch_scheduled_runs_for_schedule(instance,
                                       logger,
                                       schedule_state,
                                       end_datetime_utc,
                                       max_catchup_runs,
                                       debug_crash_flags=None):
    check.inst_param(instance, "instance", DagsterInstance)
    check.inst_param(schedule_state, "schedule_state", ScheduleState)
    check.inst_param(end_datetime_utc, "end_datetime_utc", datetime.datetime)

    latest_tick = instance.get_latest_tick(schedule_state.schedule_origin_id)

    if not latest_tick:
        start_timestamp_utc = schedule_state.start_timestamp
    elif latest_tick.status == ScheduleTickStatus.STARTED:
        # Scheduler was interrupted while performing this tick, re-do it
        start_timestamp_utc = latest_tick.timestamp
    else:
        start_timestamp_utc = latest_tick.timestamp + 1

    start_datetime_utc = datetime.datetime.fromtimestamp(start_timestamp_utc,
                                                         tz=get_utc_timezone())

    tick_times = list(
        croniter_range(start_datetime_utc, end_datetime_utc,
                       schedule_state.cron_schedule))

    if not tick_times:
        logger.info("No new runs for {schedule_name}".format(
            schedule_name=schedule_state.name))
        return

    if len(tick_times) > max_catchup_runs:
        logger.warn(
            "{schedule_name} has fallen behind, only launching {max_catchup_runs} runs"
            .format(schedule_name=schedule_state.name,
                    max_catchup_runs=max_catchup_runs))
        tick_times = tick_times[-max_catchup_runs:]

    if len(tick_times) == 1:
        logger.info("Launching run for {schedule_name} at {time}".format(
            schedule_name=schedule_state.name,
            time=tick_times[0].strftime(_SCHEDULER_DATETIME_FORMAT),
        ))
    else:
        logger.info(
            "Launching {num_runs} runs for {schedule_name} at the following times: {times}"
            .format(
                num_runs=len(tick_times),
                schedule_name=schedule_state.name,
                times=", ".join([
                    time.strftime(_SCHEDULER_DATETIME_FORMAT)
                    for time in tick_times
                ]),
            ))

    for schedule_time_utc in tick_times:
        schedule_timestamp = get_timestamp_from_utc_datetime(schedule_time_utc)
        if latest_tick and latest_tick.timestamp == schedule_timestamp:
            tick = latest_tick
            logger.info("Resuming previously interrupted schedule execution")

        else:
            tick = instance.create_schedule_tick(
                ScheduleTickData(
                    schedule_origin_id=schedule_state.schedule_origin_id,
                    schedule_name=schedule_state.name,
                    timestamp=schedule_timestamp,
                    cron_schedule=schedule_state.cron_schedule,
                    status=ScheduleTickStatus.STARTED,
                ))

            _check_for_debug_crash(debug_crash_flags, "TICK_CREATED")

        with ScheduleTickHolder(tick, instance, logger) as tick_holder:

            _check_for_debug_crash(debug_crash_flags, "TICK_HELD")

            with RepositoryLocationHandle.create_from_repository_origin(
                    schedule_state.origin.repository_origin,
                    instance) as repo_location_handle:
                repo_location = RepositoryLocation.from_handle(
                    repo_location_handle)
                _schedule_run_at_time(
                    instance,
                    logger,
                    repo_location,
                    schedule_state,
                    schedule_time_utc,
                    tick_holder,
                    debug_crash_flags,
                )
Beispiel #16
0
def start(interval=None,
          log_to_file=True,
          strage='local',
          show_secret=False,
          onebyone=False):
    strages = ['local', 'travis', 'tencent']
    if strage not in strages:
        strage = 'local'
    if log_to_file:
        fh = logging.FileHandler('hostloc.log', mode='a')
        fh.setLevel(logging.INFO)
        fh.setFormatter(formatter)
        logger.addHandler(fh)
    if strage == 'tencent':
        pass
    else:
        if show_secret:
            logger.debug('本机IP: %s', get_ip())
        else:
            logger.debug('本机IP: %s', secret_log)

    logger.debug('onebyone: %s', onebyone)
    if onebyone:
        user_length = len(accounts)
        cron_match = None
        with open('.github/workflows/hostloc.yml', 'r') as f:
            cron_match = re.search(r"- cron: '(.*)'", f.read())

        if cron_match:
            cronsetting = cron_match.group(1)
            now = datetime.datetime.now()
            start_dt = datetime.datetime.combine(datetime.date.today(),
                                                 datetime.time.min)
            end_dt = datetime.datetime.combine(datetime.date.today(),
                                               datetime.time.max)
            cronlist = list(croniter_range(start_dt, end_dt, cronsetting))

            for i in enumerate(cronlist):
                num, dt = i
                if num == user_length:
                    break
                elif now < dt:
                    logger.debug('正在执行第%s个任务...', num)
                    hostloc_checkin_retry(accounts[num - 1],
                                          retry=3,
                                          strage=strage,
                                          show_secret=show_secret)
                    logger.debug('第%s个任务完成...', num)
                    break
                elif dt == cronlist[-1]:
                    _first = True
                    _wait_time = interval or 5 * 60
                    for account in accounts[num:]:
                        if not _first:
                            logger.debug('等待%s分钟处理下一个任务', _wait_time // 60)
                            time.sleep(int(_wait_time))
                        _first = False
                        hostloc_checkin_retry(account,
                                              retry=3,
                                              strage=strage,
                                              show_secret=show_secret)
                    logger.info('========= 今日任务完成 ==========')
    else:
        _first = True
        _wait_time = interval or 5 * 60
        for account in accounts:
            if not _first:
                logger.debug('等待%s分钟处理下一个任务', _wait_time // 60)
                time.sleep(int(_wait_time))
            _first = False
            hostloc_checkin_retry(account,
                                  retry=3,
                                  strage=strage,
                                  show_secret=show_secret)
        logger.info('========= 今日任务完成 ==========')