diff --git a/.github/workflows/dev_python3_10.yml b/.github/workflows/dev_python3_10.yml index fc27958..ada2236 100644 --- a/.github/workflows/dev_python3_10.yml +++ b/.github/workflows/dev_python3_10.yml @@ -87,11 +87,6 @@ jobs: - name: Test Create Project Function run: python ./test/unit_test/create_project_file/create_project_test.py - - name: Test Interval Scheduler - run: python ./test/unit_test/scheduler_test/sec_interval_test.py - - name: Test Cron Scheduler - run: python ./test/unit_test/scheduler_test/sec_cron_test.py - - name: Test Get Mouse Info run: python ./test/unit_test/get_info/mouse_info.py - name: Test Get Special Info diff --git a/.github/workflows/dev_python3_11.yml b/.github/workflows/dev_python3_11.yml index 85d2359..8d1ca4b 100644 --- a/.github/workflows/dev_python3_11.yml +++ b/.github/workflows/dev_python3_11.yml @@ -87,11 +87,6 @@ jobs: - name: Test Create Project Function run: python ./test/unit_test/create_project_file/create_project_test.py - - name: Test Interval Scheduler - run: python ./test/unit_test/scheduler_test/sec_interval_test.py - - name: Test Cron Scheduler - run: python ./test/unit_test/scheduler_test/sec_cron_test.py - - name: Test Get Mouse Info run: python ./test/unit_test/get_info/mouse_info.py - name: Test Get Special Info diff --git a/.github/workflows/dev_python3_9.yml b/.github/workflows/dev_python3_9.yml index 82a6b92..74155a3 100644 --- a/.github/workflows/dev_python3_9.yml +++ b/.github/workflows/dev_python3_9.yml @@ -87,11 +87,6 @@ jobs: - name: Test Create Project Function run: python ./test/unit_test/create_project_file/create_project_test.py - - name: Test Interval Scheduler - run: python ./test/unit_test/scheduler_test/sec_interval_test.py - - name: Test Cron Scheduler - run: python ./test/unit_test/scheduler_test/sec_cron_test.py - - name: Test Get Mouse Info run: python ./test/unit_test/get_info/mouse_info.py - name: Test Get Special Info diff --git a/.github/workflows/stable_python3_10.yml b/.github/workflows/stable_python3_10.yml index 0cbbd5e..e595c68 100644 --- a/.github/workflows/stable_python3_10.yml +++ b/.github/workflows/stable_python3_10.yml @@ -87,11 +87,6 @@ jobs: - name: Test Create Project Function run: python ./test/unit_test/create_project_file/create_project_test.py - - name: Test Interval Scheduler - run: python ./test/unit_test/scheduler_test/sec_interval_test.py - - name: Test Cron Scheduler - run: python ./test/unit_test/scheduler_test/sec_cron_test.py - - name: Test Get Mouse Info run: python ./test/unit_test/get_info/mouse_info.py - name: Test Get Special Info diff --git a/.github/workflows/stable_python3_11.yml b/.github/workflows/stable_python3_11.yml index d869749..0ea06d4 100644 --- a/.github/workflows/stable_python3_11.yml +++ b/.github/workflows/stable_python3_11.yml @@ -87,11 +87,6 @@ jobs: - name: Test Create Project Function run: python ./test/unit_test/create_project_file/create_project_test.py - - name: Test Interval Scheduler - run: python ./test/unit_test/scheduler_test/sec_interval_test.py - - name: Test Cron Scheduler - run: python ./test/unit_test/scheduler_test/sec_cron_test.py - - name: Test Get Mouse Info run: python ./test/unit_test/get_info/mouse_info.py - name: Test Get Special Info diff --git a/.github/workflows/stable_python3_9.yml b/.github/workflows/stable_python3_9.yml index 5a7eb03..3bcd233 100644 --- a/.github/workflows/stable_python3_9.yml +++ b/.github/workflows/stable_python3_9.yml @@ -87,11 +87,6 @@ jobs: - name: Test Create Project Function run: python ./test/unit_test/create_project_file/create_project_test.py - - name: Test Interval Scheduler - run: python ./test/unit_test/scheduler_test/sec_interval_test.py - - name: Test Cron Scheduler - run: python ./test/unit_test/scheduler_test/sec_cron_test.py - - name: Test Get Mouse Info run: python ./test/unit_test/get_info/mouse_info.py - name: Test Get Special Info diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 040ae0b..56249f8 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -5,8 +5,13 @@ - - + + + + + + + + { + "lastFilter": { + "state": "OPEN", + "assignee": "JE-Chen" + } +} @@ -37,6 +48,12 @@ + { + "selectedUrlAndAccountId": { + "url": "https://github.com/Integration-Automation/AutoControlGUI.git", + "accountId": "a99e3205-1b0b-4362-b014-5d2163fb0c3a" + } +} @@ -61,33 +78,33 @@ - { + "keyToString": { + "DefaultHtmlFileTemplate": "HTML File", + "Python.calculator.executor": "Run", + "Python.callback_test.executor": "Run", + "Python.create_project_test.executor": "Run", + "Python.critical_exit_test.executor": "Run", + "Python.executor_one_file.executor": "Run", + "Python.screen_test.executor": "Run", + "Python.screenshot_test.executor": "Run", + "Python.video_recording.executor": "Run", + "RunOnceActivity.OpenProjectViewOnStart": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.git.unshallow": "true", + "WebServerToolWindowFactoryState": "false", + "git-widget-placeholder": "dev", + "ignore.virus.scanning.warn.message": "true", + "last_opened_file_path": "C:/CodeWorkspace/Python/AutoControlGUI", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "settings.editor.selected.configurable": "discord-application", + "vue.rearranger.settings.migration": "true" } -}]]> +} @@ -233,8 +250,8 @@ - @@ -552,6 +569,13 @@ + + + + + + + diff --git a/dev.toml b/dev.toml index fb8a3b2..6e70478 100644 --- a/dev.toml +++ b/dev.toml @@ -6,18 +6,17 @@ build-backend = "setuptools.build_meta" [project] name = "je_auto_control_dev" -version = "0.0.106" +version = "0.0.107" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] description = "GUI Automation Framework" requires-python = ">=3.9" -license = { text = "MIT" } +license-files = ["LICENSE"] dependencies = [ "je_open_cv", "pillow", - "APScheduler", - "Pyside6", + "Pyside6==6.8.2.1", "pyobjc-core;platform_system=='Darwin'", "pyobjc;platform_system=='Darwin'", "python-Xlib;platform_system=='Linux'", @@ -29,7 +28,6 @@ classifiers = [ "Environment :: Win32 (MS Windows)", "Environment :: MacOS X", "Environment :: X11 Applications", - "License :: OSI Approved :: MIT License", "Operating System :: OS Independent" ] @@ -42,9 +40,6 @@ Code = "https://github.com/Intergration-Automation-Testing/AutoControl" file = "README.md" content-type = "text/markdown" -[tool.setuptools] -license-files = ["LICENSE"] - [tool.setuptools.packages] find = { namespaces = false } diff --git a/dev_requirements.txt b/dev_requirements.txt index 588b9e5..ae6f73a 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -4,6 +4,6 @@ build twine sphinx sphinx-rtd-theme -Pyside6==6.8.1 +Pyside6==6.8.2.1 qt-material mss diff --git a/je_auto_control/__init__.py b/je_auto_control/__init__.py index 0206913..34b2d2b 100644 --- a/je_auto_control/__init__.py +++ b/je_auto_control/__init__.py @@ -60,8 +60,6 @@ package_manager from je_auto_control.utils.project.create_project_structure import \ create_project_dir -# Scheduler -from je_auto_control.utils.scheduler.extend_apscheduler import SchedulerManager # Shell command from je_auto_control.utils.shell_process.shell_exec import ShellManager from je_auto_control.utils.shell_process.shell_exec import default_shell_manager @@ -104,6 +102,8 @@ # import screen from je_auto_control.wrapper.auto_control_screen import screen_size from je_auto_control.wrapper.auto_control_screen import screenshot +# Recording +from je_auto_control.utils.cv2_utils.video_recording import RecordingThread __all__ = [ "click_mouse", "mouse_keys_table", "get_mouse_position", "press_mouse", "release_mouse", @@ -120,5 +120,5 @@ "generate_html", "generate_html_report", "generate_json", "generate_json_report", "generate_xml", "generate_xml_report", "get_dir_files_as_list", "create_project_dir", "start_autocontrol_socket_server", "callback_executor", "package_manager", "get_special_table", "ShellManager", "default_shell_manager", - "SchedulerManager" + "RecordingThread" ] diff --git a/je_auto_control/utils/downloading/__init__.py b/je_auto_control/utils/downloading/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/je_auto_control/utils/downloading/file_download.py b/je_auto_control/utils/downloading/file_download.py deleted file mode 100644 index 8662154..0000000 --- a/je_auto_control/utils/downloading/file_download.py +++ /dev/null @@ -1,12 +0,0 @@ -import urllib.request -import shutil - -from je_auto_control.utils.logging.loggin_instance import autocontrol_logger - - -def download_file(url: str, file_name: str): - autocontrol_logger.info("file_download.py download_file" - f" url: {url} " - f" file_name: {file_name}") - with urllib.request.urlopen(url) as response, open(file_name, 'wb') as out_file: - shutil.copyfileobj(response, out_file) \ No newline at end of file diff --git a/je_auto_control/utils/executor/action_executor.py b/je_auto_control/utils/executor/action_executor.py index 93a50c1..af0a5e2 100644 --- a/je_auto_control/utils/executor/action_executor.py +++ b/je_auto_control/utils/executor/action_executor.py @@ -18,7 +18,6 @@ from je_auto_control.utils.logging.loggin_instance import autocontrol_logger from je_auto_control.utils.package_manager.package_manager_class import package_manager from je_auto_control.utils.project.create_project_structure import create_project_dir -from je_auto_control.utils.scheduler.extend_apscheduler import scheduler_manager from je_auto_control.utils.shell_process.shell_exec import ShellManager from je_auto_control.utils.start_exe.start_another_process import start_exe from je_auto_control.utils.test_record.record_test_class import record_action_to_list, test_record_instance @@ -90,15 +89,6 @@ def __init__(self): "AC_shell_command": ShellManager().exec_shell, # Another process "AC_execute_process": start_exe, - # Scheduler - "AC_scheduler_event_trigger": self.scheduler_event_trigger, - "AC_remove_blocking_scheduler_job": scheduler_manager.remove_blocking_job, - "AC_remove_nonblocking_scheduler_job": scheduler_manager.remove_nonblocking_job, - "AC_start_blocking_scheduler": scheduler_manager.start_block_scheduler, - "AC_start_nonblocking_scheduler": scheduler_manager.start_nonblocking_scheduler, - "AC_start_all_scheduler": scheduler_manager.start_all_scheduler, - "AC_shutdown_blocking_scheduler": scheduler_manager.shutdown_blocking_scheduler, - "AC_shutdown_nonblocking_scheduler": scheduler_manager.shutdown_nonblocking_scheduler, } # get all builtin function and add to event dict for function in getmembers(builtins, isbuiltin): @@ -164,15 +154,6 @@ def execute_files(self, execute_files_list: list) -> List[Dict[str, str]]: execute_detail_list.append(self.execute_action(read_action_json(file))) return execute_detail_list - def scheduler_event_trigger( - self, function: str, scheduler_id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, scheduler_type: str = "nonblocking", wait_type: str = "secondly", - wait_value: int = 1, **trigger_args: Any) -> None: - if scheduler_type == "nonblocking": - scheduler_event = scheduler_manager.nonblocking_scheduler_event_dict.get(wait_type) - else: - scheduler_event = scheduler_manager.blocking_scheduler_event_dict.get(wait_type) - scheduler_event(self.event_dict.get(function), scheduler_id, args, kwargs, wait_value, **trigger_args) executor = Executor() diff --git a/je_auto_control/utils/scheduler/__init__.py b/je_auto_control/utils/scheduler/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/je_auto_control/utils/scheduler/extend_apscheduler.py b/je_auto_control/utils/scheduler/extend_apscheduler.py deleted file mode 100644 index 36abd01..0000000 --- a/je_auto_control/utils/scheduler/extend_apscheduler.py +++ /dev/null @@ -1,215 +0,0 @@ -from datetime import datetime -from typing import Callable, Any, Union - -from apscheduler.job import Job -from apscheduler.schedulers.background import BackgroundScheduler -from apscheduler.schedulers.blocking import BlockingScheduler -from apscheduler.util import undefined - - -class SchedulerManager(object): - - def __init__(self): - self._blocking_schedulers: BlockingScheduler = BlockingScheduler() - self._background_schedulers: BackgroundScheduler = BackgroundScheduler() - self.blocking_scheduler_event_dict = { - "secondly": self.add_interval_blocking_secondly, - "minutely": self.add_interval_blocking_minutely, - "hourly": self.add_interval_blocking_hourly, - "daily": self.add_interval_blocking_daily, - "weekly": self.add_interval_blocking_weekly, - } - self.nonblocking_scheduler_event_dict = { - "secondly": self.add_interval_nonblocking_secondly, - "minutely": self.add_interval_nonblocking_minutely, - "hourly": self.add_interval_nonblocking_hourly, - "daily": self.add_interval_nonblocking_daily, - "weekly": self.add_interval_nonblocking_weekly, - } - - def add_blocking_job( - self, func: Callable, trigger: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, id: str = None, name: str = None, - misfire_grace_time: int = undefined, coalesce: bool = undefined, max_instances: int = undefined, - next_run_time: datetime = undefined, jobstore: str = 'default', executor: str = 'default', - replace_existing: bool = False, **trigger_args: Any) -> Job: - """ - Just an apscheduler add job wrapper. - :param func: callable (or a textual reference to one) to run at the given time - :param str|apscheduler.triggers.base.BaseTrigger trigger: trigger that determines when - ``func`` is called - :param list|tuple args: list of positional arguments to call func with - :param dict kwargs: dict of keyword arguments to call func with - :param str|unicode id: explicit identifier for the job (for modifying it later) - :param str|unicode name: textual description of the job - :param int misfire_grace_time: seconds after the designated runtime that the job is still - allowed to be run (or ``None`` to allow the job to run no matter how late it is) - :param bool coalesce: run once instead of many times if the scheduler determines that the - job should be run more than once in succession - :param int max_instances: maximum number of concurrently running instances allowed for this - job - :param datetime next_run_time: when to first run the job, regardless of the trigger (pass - ``None`` to add the job as paused) - :param str|unicode jobstore: alias of the job store to store the job in - :param str|unicode executor: alias of the executor to run the job with - :param bool replace_existing: ``True`` to replace an existing job with the same ``id`` - (but retain the number of runs from the existing one) - :return: Job - """ - params = locals() - params.pop("self") - params.pop("trigger_args") - return self._blocking_schedulers.add_job(**params, **trigger_args) - - def add_nonblocking_job( - self, func: Callable, trigger: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, id: str = None, name: str = None, - misfire_grace_time: int = undefined, coalesce: bool = undefined, max_instances: int = undefined, - next_run_time: datetime = undefined, jobstore: str = 'default', executor: str = 'default', - replace_existing: bool = False, **trigger_args: Any) -> Job: - """ - Just an apscheduler add job wrapper. - :param func: callable (or a textual reference to one) to run at the given time - :param str|apscheduler.triggers.base.BaseTrigger trigger: trigger that determines when - ``func`` is called - :param list|tuple args: list of positional arguments to call func with - :param dict kwargs: dict of keyword arguments to call func with - :param str|unicode id: explicit identifier for the job (for modifying it later) - :param str|unicode name: textual description of the job - :param int misfire_grace_time: seconds after the designated runtime that the job is still - allowed to be run (or ``None`` to allow the job to run no matter how late it is) - :param bool coalesce: run once instead of many times if the scheduler determines that the - job should be run more than once in succession - :param int max_instances: maximum number of concurrently running instances allowed for this - job - :param datetime next_run_time: when to first run the job, regardless of the trigger (pass - ``None`` to add the job as paused) - :param str|unicode jobstore: alias of the job store to store the job in - :param str|unicode executor: alias of the executor to run the job with - :param bool replace_existing: ``True`` to replace an existing job with the same ``id`` - (but retain the number of runs from the existing one) - :return: Job - """ - params = locals() - params.pop("self") - params.pop("trigger_args") - return self._background_schedulers.add_job(**params, **trigger_args) - - def get_blocking_scheduler(self) -> BlockingScheduler: - """ - Return self blocking scheduler - :return: BlockingScheduler - """ - return self._blocking_schedulers - - def get_nonblocking_scheduler(self) -> BackgroundScheduler: - """ - Return self background scheduler - :return: BackgroundScheduler - """ - return self._background_schedulers - - def start_block_scheduler(self, *args: Any, **kwargs: Any) -> None: - """ - Start blocking scheduler - :return: None - """ - self._blocking_schedulers.start(*args, **kwargs) - - def start_nonblocking_scheduler(self, *args: Any, **kwargs: Any) -> None: - """ - Start background scheduler - :return: None - """ - self._background_schedulers.start(*args, **kwargs) - - def start_all_scheduler(self, *args: Any, **kwargs: Any) -> None: - """ - Start background and blocking scheduler - :return: None - """ - self._blocking_schedulers.start(*args, **kwargs) - self._background_schedulers.start(*args, **kwargs) - - def add_interval_blocking_secondly( - self, function: Callable, id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, seconds: int = 1, **trigger_args: Any) -> Job: - return self.add_blocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, seconds=seconds, **trigger_args) - - def add_interval_blocking_minutely( - self, function: Callable, id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, minutes: int = 1, **trigger_args: Any) -> Job: - return self.add_blocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, minutes=minutes, **trigger_args) - - def add_interval_blocking_hourly( - self, function: Callable, id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, hours: int = 1, **trigger_args: Any) -> Job: - return self.add_blocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, hours=hours, **trigger_args) - - def add_interval_blocking_daily( - self, function: Callable, id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, days: int = 1, **trigger_args: Any) -> Job: - return self.add_blocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, days=days, **trigger_args) - - def add_interval_blocking_weekly( - self, function: Callable, id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, weeks: int = 1, **trigger_args: Any) -> Job: - return self.add_blocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, weeks=weeks, **trigger_args) - - def add_interval_nonblocking_secondly( - self, function: Callable, id: str = None, args: list = None, - kwargs: dict = None, seconds: int = 1, **trigger_args: Any) -> Job: - return self.add_nonblocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, seconds=seconds, **trigger_args) - - def add_interval_nonblocking_minutely( - self, function: Callable, id: str = None, args: list = None, - kwargs: dict = None, minutes: int = 1, **trigger_args: Any) -> Job: - return self.add_nonblocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, minutes=minutes, **trigger_args) - - def add_interval_nonblocking_hourly( - self, function: Callable, id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, hours: int = 1, **trigger_args: Any) -> Job: - return self.add_nonblocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, hours=hours, **trigger_args) - - def add_interval_nonblocking_daily( - self, function: Callable, id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, days: int = 1, **trigger_args: Any) -> Job: - return self.add_nonblocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, days=days, **trigger_args) - - def add_interval_nonblocking_weekly( - self, function: Callable, id: str = None, args: Union[list, tuple] = None, - kwargs: dict = None, weeks: int = 1, **trigger_args: Any) -> Job: - return self.add_nonblocking_job( - func=function, trigger="interval", id=id, args=args, kwargs=kwargs, weeks=weeks, **trigger_args) - - def add_cron_blocking( - self, function: Callable, id: str = None, **trigger_args: Any) -> Job: - return self.add_blocking_job(func=function, id=id, trigger="cron", **trigger_args) - - def add_cron_nonblocking( - self, function: Callable, id: str = None, **trigger_args: Any) -> Job: - return self.add_nonblocking_job(func=function, id=id, trigger="cron", **trigger_args) - - def remove_blocking_job(self, id: str, jobstore: str = 'default') -> Any: - return self._blocking_schedulers.remove_job(job_id=id, jobstore=jobstore) - - def remove_nonblocking_job(self, id: str, jobstore: str = 'default') -> Any: - return self._background_schedulers.remove_job(job_id=id, jobstore=jobstore) - - def shutdown_blocking_scheduler(self, wait: bool = False) -> None: - self._blocking_schedulers.shutdown(wait=wait) - - def shutdown_nonblocking_scheduler(self, wait: bool = False) -> None: - self._background_schedulers.shutdown(wait=wait) - - -scheduler_manager = SchedulerManager() diff --git a/pyproject.toml b/pyproject.toml index efe2223..9ddfcb9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,18 +6,17 @@ build-backend = "setuptools.build_meta" [project] name = "je_auto_control" -version = "0.0.163" +version = "0.0.164" authors = [ { name = "JE-Chen", email = "jechenmailman@gmail.com" }, ] description = "GUI Automation Framework" requires-python = ">=3.9" -license = { text = "MIT" } +license-files = ["LICENSE"] dependencies = [ "je_open_cv", "pillow", - "Pyside6", - "APScheduler", + "Pyside6==6.8.2.1", "pyobjc-core;platform_system=='Darwin'", "pyobjc;platform_system=='Darwin'", "python-Xlib;platform_system=='Linux'", @@ -29,7 +28,6 @@ classifiers = [ "Environment :: Win32 (MS Windows)", "Environment :: MacOS X", "Environment :: X11 Applications", - "License :: OSI Approved :: MIT License", "Operating System :: OS Independent" ] @@ -42,9 +40,6 @@ Code = "https://github.com/Intergration-Automation-Testing/AutoControl" file = "README.md" content-type = "text/markdown" -[tool.setuptools] -license-files = ["LICENSE"] - [tool.setuptools.packages] find = { namespaces = false } diff --git a/test/unit_test/scheduler_test/sec_cron_test.py b/test/unit_test/scheduler_test/sec_cron_test.py deleted file mode 100644 index a48b236..0000000 --- a/test/unit_test/scheduler_test/sec_cron_test.py +++ /dev/null @@ -1,12 +0,0 @@ -from je_auto_control import SchedulerManager - - -def test_scheduler(): - print("Test Scheduler") - scheduler.remove_blocking_job(id="test") - scheduler.shutdown_blocking_scheduler() - - -scheduler = SchedulerManager() -scheduler.add_cron_blocking(function=test_scheduler, id="test", second="*") -scheduler.start_block_scheduler() diff --git a/test/unit_test/scheduler_test/sec_interval_test.py b/test/unit_test/scheduler_test/sec_interval_test.py deleted file mode 100644 index dc3db2b..0000000 --- a/test/unit_test/scheduler_test/sec_interval_test.py +++ /dev/null @@ -1,12 +0,0 @@ -from je_auto_control import SchedulerManager - - -def test_scheduler(): - print("Test Scheduler") - scheduler.remove_blocking_job(id="test") - scheduler.shutdown_blocking_scheduler() - - -scheduler = SchedulerManager() -scheduler.add_interval_blocking_secondly(function=test_scheduler, id="test") -scheduler.start_block_scheduler()