Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add Parameter pattern to JobQueue.jobs() #4613

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
34 changes: 29 additions & 5 deletions telegram/ext/_jobqueue.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"""This module contains the classes JobQueue and Job."""
import asyncio
import datetime as dtm
import re
import weakref
from typing import TYPE_CHECKING, Any, Generic, Optional, Union, cast, overload

Expand All @@ -38,6 +39,8 @@
from telegram.ext._utils.types import CCT, JobCallback

if TYPE_CHECKING:
from collections.abc import Iterable

if APS_AVAILABLE:
from apscheduler.job import Job as APSJob

Expand Down Expand Up @@ -695,22 +698,43 @@
# so give it a tiny bit of time to actually shut down.
await asyncio.sleep(0.01)

def jobs(self) -> tuple["Job[CCT]", ...]:
def jobs(self, pattern: Union[str, re.Pattern[str], None] = None) -> tuple["Job[CCT]", ...]:
"""Returns a tuple of all *scheduled* jobs that are currently in the :class:`JobQueue`.

Args:
pattern (:obj:`str` | :obj:`re.Pattern`, optional): A regular expression pattern. If
passed, only jobs whose name matches the pattern will be returned.
Defaults to :obj:`None`.

Hint:
This uses :func:`re.search` and not :func:`re.match`.

.. versionadded:: NEXT.VERSION

Returns:
tuple[:class:`Job`]: Tuple of all *scheduled* jobs.
"""
return tuple(Job.from_aps_job(job) for job in self.scheduler.get_jobs())
jobs_generator: Iterable[Job] = (

Check warning on line 717 in telegram/ext/_jobqueue.py

View check run for this annotation

Codecov / codecov/patch

telegram/ext/_jobqueue.py#L717

Added line #L717 was not covered by tests
Job.from_aps_job(job) for job in self.scheduler.get_jobs()
)
if pattern is None:
return tuple(jobs_generator)
return tuple(

Check warning on line 722 in telegram/ext/_jobqueue.py

View check run for this annotation

Codecov / codecov/patch

telegram/ext/_jobqueue.py#L721-L722

Added lines #L721 - L722 were not covered by tests
job for job in jobs_generator if (job.name and re.compile(pattern).search(job.name))
)

def get_jobs_by_name(self, name: str) -> tuple["Job[CCT]", ...]:
"""Returns a tuple of all *pending/scheduled* jobs with the given name that are currently
"""Returns a tuple of all *scheduled* jobs with the given name that are currently
in the :class:`JobQueue`.

Hint:
This method is a convenience wrapper for :meth:`jobs` with a pattern that matches the
given name.

Returns:
tuple[:class:`Job`]: Tuple of all *pending* or *scheduled* jobs matching the name.
tuple[:class:`Job`]: Tuple of all *scheduled* jobs matching the name.
"""
return tuple(job for job in self.jobs() if job.name == name)
return self.jobs(f"^{re.escape(name)}$")

Check warning on line 737 in telegram/ext/_jobqueue.py

View check run for this annotation

Codecov / codecov/patch

telegram/ext/_jobqueue.py#L737

Added line #L737 was not covered by tests


class Job(Generic[CCT]):
Expand Down
30 changes: 23 additions & 7 deletions tests/ext/test_jobqueue.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import datetime as dtm
import logging
import platform
import re
import time

import pytest
Expand Down Expand Up @@ -462,19 +463,34 @@ async def test_default_tzinfo(self, tz_bot):

await jq.stop()

async def test_get_jobs(self, job_queue):
@pytest.mark.parametrize(
"pattern", [None, "not", re.compile("not")], ids=["None", "str", "re.Pattern"]
)
async def test_get_jobs(self, job_queue, pattern):
callback = self.job_run_once

job1 = job_queue.run_once(callback, 10, name="name1")
job1 = job_queue.run_once(callback, 10, name="is|a|match")
await asyncio.sleep(0.03) # To stablize tests on windows
job2 = job_queue.run_once(callback, 10, name="name1")
job2 = job_queue.run_once(callback, 10, name="is|a|match")
await asyncio.sleep(0.03)
job3 = job_queue.run_once(callback, 10, name="name2")
job3 = job_queue.run_once(callback, 10, name="not|is|a|match")
await asyncio.sleep(0.03)
job4 = job_queue.run_once(callback, 10, name="is|a|match|not")
await asyncio.sleep(0.03)
job5 = job_queue.run_once(callback, 10, name="something_else")
await asyncio.sleep(0.03)
# name-less job
job6 = job_queue.run_once(callback, 10)
await asyncio.sleep(0.03)

if pattern is None:
assert job_queue.jobs(pattern) == (job1, job2, job3, job4, job5, job6)
else:
assert job_queue.jobs(pattern) == (job3, job4)

assert job_queue.jobs() == (job1, job2, job3)
assert job_queue.get_jobs_by_name("name1") == (job1, job2)
assert job_queue.get_jobs_by_name("name2") == (job3,)
assert job_queue.jobs() == (job1, job2, job3, job4, job5, job6)
assert job_queue.get_jobs_by_name("is|a|match") == (job1, job2)
assert job_queue.get_jobs_by_name("something_else") == (job5,)

async def test_job_run(self, app):
job = app.job_queue.run_repeating(self.job_run_once, 0.02)
Expand Down
Loading