Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

imlemented crontab based repeating job for jobqueue#1478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletionsrequirements.txt
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
future>=0.16.0
certifi
tornado>=5.1
croniter
cryptography
33 changes: 26 additions & 7 deletionstelegram/ext/jobqueue.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -23,6 +23,7 @@
import time
import warnings
import weakref
from croniter import croniter
from numbers import Number
from queue import PriorityQueue, Empty
from threading import Thread, Lock, Event
Expand DownExpand Up@@ -71,13 +72,14 @@ def set_dispatcher(self, dispatcher):
self._dispatcher = dispatcher

def _put(self, job, next_t=None, last_t=None):
if next_t is None:
if next_t is None and not isinstance(job.interval, str):
next_t = job.interval
if next_t is None:
raise ValueError('next_t is None')

if isinstance(next_t, datetime.datetime):
next_t = (next_t - datetime.datetime.now()).total_seconds()
next_t += last_t or time.time()

elif isinstance(next_t, datetime.time):
next_datetime = datetime.datetime.combine(datetime.date.today(), next_t)
Expand All@@ -86,11 +88,19 @@ def _put(self, job, next_t=None, last_t=None):
next_datetime += datetime.timedelta(days=1)

next_t = (next_datetime - datetime.datetime.now()).total_seconds()
next_t += last_t or time.time()

elif isinstance(next_t, datetime.timedelta):
next_t = next_t.total_seconds()
next_t += last_t or time.time()

next_t += last_t or time.time()
elif isinstance(job.interval, str):
base = self._now()
dt = croniter(job.interval, base).get_next(datetime.datetime)
next_t = datetime.datetime.timestamp(dt)

else:
next_t += last_t or time.time()

self.logger.debug('Putting job %s with t=%f', job.name, next_t)

Expand DownExpand Up@@ -144,9 +154,11 @@ def run_repeating(self, callback, interval, first=None, context=None, name=None)
job. It should take ``bot, job`` as parameters, where ``job`` is the
:class:`telegram.ext.Job` instance. It can be used to access its
``Job.context`` or change it to a repeating job.
interval (:obj:`int` | :obj:`float` | :obj:`datetime.timedelta`): The interval in which
the job will run. If it is an :obj:`int` or a :obj:`float`, it will be interpreted
as seconds.
interval (:obj:`int` | :obj:`float` | :obj:`datetime.timedelta` |
:obj:`str`): The interval in which the job will run. If it is
an :obj:`int` or a :obj:`float`, it will be interpreted as
seconds, if it is an :obj:`str` it will be
interpreted as crontab
first (:obj:`int` | :obj:`float` | :obj:`datetime.timedelta` | \
:obj:`datetime.datetime` | :obj:`datetime.time`, optional):
Time in or at which the job should run. This parameter will be interpreted
Expand DownExpand Up@@ -335,6 +347,9 @@ def get_jobs_by_name(self, name):
with self._queue.mutex:
return tuple(job[1] for job in self._queue.queue if job and job[1].name == name)

def _now(self):
return datetime.datetime.now()


class Job(object):
"""This class encapsulates a Job.
Expand DownExpand Up@@ -438,9 +453,13 @@ def interval(self, interval):
if interval is None and self.repeat:
raise ValueError("The 'interval' can not be 'None' when 'repeat' is set to 'True'")

if not (interval is None or isinstance(interval, (Number, datetime.timedelta))):
if not (interval is None or isinstance(interval, (Number, datetime.timedelta, str))):
raise ValueError("The 'interval' must be of type 'datetime.timedelta',"
" 'int' or 'float'")
" 'int' or 'float' or 'str'")

if isinstance(interval, str):
if not croniter.is_valid(interval):
raise ValueError("The 'interval' of type 'str' must be a valid crontab")

self._interval = interval

Expand Down
22 changes: 21 additions & 1 deletiontests/test_jobqueue.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -25,6 +25,7 @@

import pytest
from flaky import flaky
from unittest.mock import patch

from telegram.ext import JobQueue, Updater, Job, CallbackContext
from telegram.utils.deprecate import TelegramDeprecationWarning
Expand DownExpand Up@@ -228,6 +229,23 @@ def test_run_daily(self, job_queue):
assert self.result == 1
assert pytest.approx(job_queue._queue.get(False)[0]) == expected_time

def test_run_cron_daily(self, job_queue):
dt = datetime.datetime(year=2019, month=1, day=1, hour=1, minute=0, second=0)
ts = datetime.datetime.timestamp(dt)
def patchDateTime() :
return dt
def patchTime() :
return ts
with patch('telegram.ext.JobQueue._now', side_effect=patchDateTime):
with patch('time.time', side_effect=patchTime):
with patch('threading.Event.wait', return_value=True):
job_queue.run_repeating(self.job_run_once, '0 2 * * *')
for i in range(24 * 7 * 2):
dt += datetime.timedelta(hours=1)
ts = datetime.datetime.timestamp(dt)
sleep(0.01)
assert self.result == 14

def test_warnings(self, job_queue):
j = Job(self.job_run_once, repeat=False)
with pytest.raises(ValueError, match='can not be set to'):
Expand All@@ -239,7 +257,9 @@ def test_warnings(self, job_queue):
j.interval = None
j.repeat = False
with pytest.raises(ValueError, match='must be of type'):
j.interval = 'every 3 minutes'
j.interval = {'every': {'minutes': 3}}
with pytest.raises(ValueError, match='must be a valid crontab'):
j.interval = '* * * janu-jun *'
j.interval = 15
assert j.interval_seconds == 15

Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp