├── .coveragerc ├── .gitattributes ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── docs ├── Makefile ├── _static │ └── css │ │ ├── colors.css │ │ └── types.css ├── code │ ├── demo.py │ ├── demo_basic.py │ ├── demos │ │ ├── advanced.py │ │ ├── basic.py │ │ ├── intermediate.py │ │ ├── minimal.py │ │ └── monitor.py │ ├── execution.py │ ├── parameter │ │ ├── parameters.py │ │ └── pipelining.py │ ├── schedule │ │ ├── fixed_period.py │ │ ├── fixed_period_with_args.py │ │ ├── logic.py │ │ └── time_of.py │ └── snippets │ │ ├── parallelization.py │ │ ├── parametrize.py │ │ ├── pipeline.py │ │ └── scheduling.py ├── condition_syntax │ ├── dependence.rst │ ├── execution.rst │ ├── fixed_interval.rst │ ├── index.rst │ ├── task_status.rst │ └── timedelta.rst ├── conf.py ├── contributing.rst ├── examples │ └── index.rst ├── favicon.ico ├── how_it_works.rst ├── index.rst ├── logo.svg ├── make.bat ├── s5defs.txt ├── scheduling.png ├── task_execution.png ├── tutorial │ ├── advanced.rst │ ├── basic.rst │ ├── index.rst │ ├── intermediate.rst │ └── quick_start.rst └── versions.rst ├── redengine ├── __init__.py ├── _base.py ├── _setup.py ├── _version.py ├── application.py ├── args │ ├── __init__.py │ ├── builtin.py │ └── secret.py ├── conditions │ ├── __init__.py │ ├── func.py │ ├── meta.py │ ├── parameter.py │ ├── scheduler.py │ ├── task │ │ ├── __init__.py │ │ ├── task.py │ │ └── utils.py │ └── time.py ├── core │ ├── __init__.py │ ├── condition │ │ ├── __init__.py │ │ ├── base.py │ │ ├── statement.py │ │ └── utils.py │ ├── hook.py │ ├── log │ │ ├── __init__.py │ │ └── adapter.py │ ├── meta.py │ ├── parameters │ │ ├── __init__.py │ │ ├── arguments.py │ │ └── parameters.py │ ├── schedule.py │ ├── task.py │ ├── time │ │ ├── __init__.py │ │ ├── anchor.py │ │ ├── base.py │ │ └── utils.py │ └── utils │ │ ├── __init__.py │ │ ├── meta.py │ │ ├── pickle.py │ │ └── process.py ├── exc.py ├── log │ ├── __init__.py │ ├── defaults.py │ ├── handlers.py │ └── log_record.py ├── parameters │ ├── __init__.py │ └── func.py ├── parse │ ├── __init__.py │ ├── _condition │ │ ├── __init__.py │ │ ├── condition_item.py │ │ └── string.py │ ├── _time │ │ ├── __init__.py │ │ ├── string.py │ │ └── time_item.py │ ├── condition.py │ ├── time.py │ └── utils │ │ ├── __init__.py │ │ ├── cond.py │ │ ├── exception.py │ │ ├── parser.py │ │ ├── string_parser.py │ │ └── utils.py ├── pybox │ ├── __init__.py │ ├── container │ │ ├── __init__.py │ │ └── visitor.py │ ├── pkg │ │ ├── __init__.py │ │ └── path.py │ ├── query │ │ ├── __init__.py │ │ ├── base.py │ │ ├── parse.py │ │ └── string.py │ └── string │ │ ├── __init__.py │ │ └── parse │ │ ├── __init__.py │ │ └── closure.py ├── session.py ├── tasks │ ├── __init__.py │ ├── code.py │ ├── command.py │ ├── func.py │ └── maintain │ │ ├── __init__.py │ │ └── os.py ├── test │ ├── __init__.py │ ├── app │ │ ├── __init__.py │ │ └── test_app.py │ ├── condition │ │ ├── __init__.py │ │ ├── task │ │ │ ├── __init__.py │ │ │ ├── test_basic.py │ │ │ ├── test_compare.py │ │ │ ├── test_set_default.py │ │ │ ├── test_time.py │ │ │ ├── test_time_executable.py │ │ │ └── test_time_optimized.py │ │ ├── test_alchemy.py │ │ ├── test_core.py │ │ ├── test_create.py │ │ ├── test_env.py │ │ ├── test_equal.py │ │ ├── test_meta.py │ │ ├── test_parse.py │ │ ├── test_parse_clause.py │ │ └── test_scheduler.py │ ├── conftest.py │ ├── helpers │ │ ├── __init__.py │ │ ├── io_helpers.py │ │ ├── log_helpers.py │ │ └── task_helpers.py │ ├── parameters │ │ ├── __init__.py │ │ ├── test_construct.py │ │ └── test_params.py │ ├── pybox │ │ ├── __init__.py │ │ └── query │ │ │ ├── __init__.py │ │ │ ├── test_core.py │ │ │ ├── test_from.py │ │ │ ├── test_query.py │ │ │ └── test_to.py │ ├── pytest.ini │ ├── schedule │ │ ├── __init__.py │ │ ├── process │ │ │ ├── __init__.py │ │ │ └── test_core.py │ │ ├── test_core.py │ │ ├── test_failure.py │ │ ├── test_from_scripts.py │ │ ├── test_methods.py │ │ ├── test_params.py │ │ ├── test_piping.py │ │ ├── test_scheduler_conditions.py │ │ ├── test_terminate.py │ │ └── test_traceback.py │ ├── session │ │ ├── __init__.py │ │ ├── params │ │ │ ├── __init__.py │ │ │ ├── test_func.py │ │ │ ├── test_params.py │ │ │ └── test_return.py │ │ ├── test_construct.py │ │ ├── test_control.py │ │ ├── test_core.py │ │ ├── test_logs.py │ │ ├── test_run.py │ │ └── test_utils.py │ ├── task │ │ ├── __init__.py │ │ ├── code │ │ │ ├── __init__.py │ │ │ └── test_construct.py │ │ ├── command │ │ │ ├── test_construct.py │ │ │ └── test_run.py │ │ ├── func │ │ │ ├── __init__.py │ │ │ ├── test_construct.py │ │ │ ├── test_export.py │ │ │ ├── test_logging.py │ │ │ ├── test_run.py │ │ │ └── test_run_delayed.py │ │ ├── misc │ │ │ ├── __init__.py │ │ │ ├── test_restart.py │ │ │ └── test_shutdown.py │ │ ├── test_core.py │ │ └── test_pickle.py │ ├── test_files │ │ ├── __init__.py │ │ ├── failing_script.py │ │ ├── parameterized_kwargs_script.py │ │ ├── parameterized_script.py │ │ ├── succeeding_script.py │ │ └── syntax_error_script.py │ ├── test_hooks.py │ └── time │ │ ├── __init__.py │ │ ├── delta │ │ ├── __init__.py │ │ ├── test_construct.py │ │ ├── test_contains.py │ │ └── test_roll.py │ │ ├── interval │ │ ├── __init__.py │ │ ├── test_construct.py │ │ ├── test_core.py │ │ ├── timeofday │ │ │ ├── __init__.py │ │ │ ├── test_contains.py │ │ │ └── test_roll.py │ │ └── timeofweek │ │ │ ├── __init__.py │ │ │ ├── test_contains.py │ │ │ └── test_core.py │ │ ├── logic │ │ ├── __init__.py │ │ └── test_roll.py │ │ ├── test_contains.py │ │ ├── test_core.py │ │ └── test_parse.py ├── time │ ├── __init__.py │ ├── construct.py │ └── interval.py └── utils │ ├── __init__.py │ └── dependencies.py ├── requirements.txt ├── requirements ├── build.txt ├── ci.txt ├── coverage.txt └── docs.txt ├── scripts └── systest │ ├── flask_api.py │ ├── load_test.py │ ├── pipelined.py │ └── timing.py ├── setup.cfg ├── setup.py ├── tox.ini └── versioneer.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source = redengine 3 | branch = False 4 | omit = 5 | test/* 6 | _version.py 7 | 8 | data_file = cov_data/.coverage 9 | 10 | [report] 11 | 12 | omit = 13 | redengine/test/* 14 | redengine/_version.py 15 | redengine/__main__.py 16 | 17 | # Regexes for lines to exclude from consideration 18 | exclude_lines = 19 | pragma: no cover 20 | 21 | # Don't complain about abstract methods, they aren't run: 22 | @(abc\.)?abstractmethod 23 | 24 | # Ignore type checking imports 25 | if TYPE_CHECKING 26 | 27 | ignore_errors = True 28 | 29 | [html] 30 | directory = htmlcov -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | redengine/_version.py export-subst 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | *pyx 6 | 7 | # Build & packaging 8 | build/* 9 | dist/* 10 | *egg-info/* 11 | 12 | # Jupyter Notebook 13 | .ipynb_checkpoints 14 | prototype* 15 | 16 | # Scrapy stuff: 17 | .scrapy 18 | 19 | draft/ 20 | private/ 21 | 22 | # Environments 23 | .env 24 | .venv 25 | env/ 26 | env_linux/ 27 | venv/ 28 | ENV/ 29 | env.bak/ 30 | venv.bak/ 31 | 32 | # IDE 33 | .vscode/ 34 | .idea/ 35 | 36 | # Testing 37 | .pytest_cache/ 38 | 39 | # Packaging 40 | build/ 41 | dist/ 42 | 43 | # Prototyping files & manual testing 44 | proto/ 45 | 46 | # Data & logs 47 | *.csv 48 | 49 | # Private configurations 50 | private.yaml 51 | 52 | # Some other random stuff 53 | bash.exe.stackdump 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # tox 59 | .tox/ 60 | 61 | # Coverage 62 | cov_data/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Mikael Koli 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include redengine/test/test_files/*.ipynb 2 | include redengine/test/test_files/*.py 3 | include redengine/config/defaults/*.json 4 | include versioneer.py 5 | include redengine/_session.py 6 | include redengine/_setup.py 7 | include redengine/_pkg.py 8 | include redengine/_version.py 9 | recursive-include redengine/templates * -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Red Engine 3 | > Powering your Python Apps 4 | 5 | 6 | ## NOTE: Red Engine has been renamed as Rocketry: https://github.com/Miksus/rocketry 7 | 8 | ----------------- 9 | 10 | [![Pypi version](https://badgen.net/pypi/v/redengine)](https://pypi.org/project/redengine/) 11 | [![build](https://github.com/Miksus/red-engine/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/Miksus/red-engine/actions/workflows/main.yml) 12 | [![codecov](https://codecov.io/gh/Miksus/red-engine/branch/master/graph/badge.svg?token=U2KF1QA5HT)](https://codecov.io/gh/Miksus/red-engine) 13 | [![Documentation Status](https://readthedocs.org/projects/red-engine/badge/?version=latest)](https://red-engine.readthedocs.io/en/latest/?badge=latest) 14 | [![PyPI pyversions](https://badgen.net/pypi/python/redengine)](https://pypi.org/project/redengine/) 15 | 16 | ## What is it? 17 | 18 | Red Engine is a modern scheduling framework for Python 19 | applications. It is simple, clean and extensive. It is 20 | the engine that sets your Python programs alive. 21 | 22 | The library is minimal on the surface but extensive 23 | and customizable underneath. The syntax very clean: 24 | 25 | ```python 26 | from redengine import RedEngine 27 | 28 | app = RedEngine() 29 | 30 | @app.task('daily') 31 | def do_daily(): 32 | ... 33 | 34 | if __name__ == '__main__': 35 | app.run() 36 | ``` 37 | 38 | Compared to alternatives, Red Engine has perhaps the most elegant syntax and is the most productive. It offers more features than Crontab or APScheduler but is much 39 | easier to work with than Airflow. It does not make assumptions of your project. 40 | 41 | Read more from the documentations: [Red Engine, documentations](https://red-engine.readthedocs.io/en/stable/) 42 | 43 | ## Installation 44 | 45 | Install Red Engine from [PyPI](https://pypi.org/project/redengine/): 46 | 47 | ```shell 48 | pip install redengine 49 | ``` 50 | 51 | 52 | ## More Examples? 53 | 54 | **Scheduling:** 55 | 56 | ```python 57 | @app.task("every 10 seconds") 58 | def do_continuously(): 59 | ... 60 | 61 | @app.task("daily after 07:00") 62 | def do_daily_after_seven(): 63 | ... 64 | 65 | @app.task("hourly & time of day between 22:00 and 06:00") 66 | def do_hourly_at_night(): 67 | ... 68 | 69 | @app.task("(weekly on Monday | weekly on Saturday) & time of day after 10:00") 70 | def do_twice_a_week_after_ten(): 71 | ... 72 | ``` 73 | 74 | **Pipelining tasks:** 75 | 76 | ```python 77 | from redengine.args import Return 78 | 79 | @app.task("daily after 07:00") 80 | def do_first(): 81 | ... 82 | return 'Hello World' 83 | 84 | @app.task("after task 'do_first'") 85 | def do_second(arg=Return('do_first')): 86 | # arg contains the value of the task do_first's return 87 | ... 88 | return 'Hello Python' 89 | ``` 90 | 91 | **Parallelizing tasks:** 92 | 93 | ```python 94 | @app.task("daily", execution="main") 95 | def do_unparallel(): 96 | ... 97 | 98 | @app.task("daily", execution="thread") 99 | def do_on_separate_thread(): 100 | ... 101 | 102 | @app.task("daily", execution="process") 103 | def do_on_separate_process(): 104 | ... 105 | ``` 106 | 107 | --- 108 | 109 | ## Author 110 | 111 | * **Mikael Koli** - [Miksus](https://github.com/Miksus) - koli.mikael@gmail.com 112 | 113 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/_static/css/colors.css: -------------------------------------------------------------------------------- 1 | 2 | .red { 3 | color: red; 4 | } -------------------------------------------------------------------------------- /docs/_static/css/types.css: -------------------------------------------------------------------------------- 1 | 2 | .py.class { 3 | padding-bottom: 20px; 4 | } -------------------------------------------------------------------------------- /docs/code/demo.py: -------------------------------------------------------------------------------- 1 | from redengine import RedEngine 2 | from redengine.args import Return 3 | 4 | app = RedEngine() 5 | 6 | @app.task('daily') 7 | def do_daily(): 8 | "This function runs once a day" 9 | ... 10 | 11 | @app.task('daily between 07:00 and 10:00 | daily between 16:00 and 20:00') 12 | def do_twice_a_day(): 13 | "This function runs twice a day (in the morning and in the afternoon)" 14 | # The '|' means OR operator. Fully supports logical operations. 15 | ... 16 | 17 | @app.task("after task 'do_daily'") 18 | def do_after_another(arg=Return('do_daily')): 19 | "Run after 'do_daily' task" 20 | # The parameter 'arg' has the return value of the function 'do_daily' 21 | ... 22 | 23 | if __name__ == "__main__": 24 | # Start the scheduler 25 | app.run() -------------------------------------------------------------------------------- /docs/code/demo_basic.py: -------------------------------------------------------------------------------- 1 | from redengine import RedEngine 2 | 3 | app = RedEngine() 4 | 5 | @app.task('daily') 6 | def do_things(): 7 | ... 8 | 9 | @app.task("after task 'do_things'") 10 | def do_after_things(): 11 | ... 12 | 13 | if __name__ == "__main__": 14 | app.run() -------------------------------------------------------------------------------- /docs/code/demos/advanced.py: -------------------------------------------------------------------------------- 1 | from redengine import RedEngine 2 | from redengine.args import Return, Arg, FuncArg 3 | 4 | app = RedEngine() 5 | 6 | # Custom Condition 7 | # ---------------- 8 | 9 | @app.cond('is foo') 10 | def is_foo(): 11 | # This is a custom condition 12 | ... 13 | return True 14 | 15 | # Parameters 16 | # ---------- 17 | 18 | app.params(my_arg='Hello') 19 | 20 | @app.param('item') 21 | def get_item(): 22 | # This is a custom condition 23 | ... 24 | return 'world' 25 | 26 | # Tasks 27 | # ----- 28 | 29 | @app.task('daily', execution="process") 30 | def do_on_process(): 31 | "This task runs once a day and runs on separate process" 32 | ... 33 | return ... 34 | 35 | @app.task("after task 'do_things'") 36 | def do_pipeline(arg1=Return('do_on_process'), 37 | arg2=Arg('item'), 38 | arg3=Arg('my_arg')): 39 | """This task runs when 'do_on_process' has succeeded. 40 | Argument 'arg1' gets the return value of 'do_on_process' 41 | Argument 'arg2' gets the return value of function 'get_item' 42 | Argument 'arg3' is simply the value of a session parameter 'my_arg'""" 43 | ... 44 | 45 | @app.task('daily & is foo', execution="thread") 46 | def do_custom(): 47 | """This task runs once a day and when is_foo returns True 48 | This task runs on separate thread""" 49 | ... 50 | 51 | @app.task('(true & true) | (false & True & ~True)') 52 | def do_complex(): 53 | """Notice the logical expression in the task start condition""" 54 | ... 55 | 56 | if __name__ == "__main__": 57 | app.run() -------------------------------------------------------------------------------- /docs/code/demos/basic.py: -------------------------------------------------------------------------------- 1 | from redengine import RedEngine 2 | 3 | app = RedEngine() 4 | 5 | @app.task('daily') 6 | def do_things(): 7 | ... 8 | 9 | @app.task("after task 'do_things'") 10 | def do_after_things(): 11 | ... 12 | 13 | if __name__ == "__main__": 14 | app.run() -------------------------------------------------------------------------------- /docs/code/demos/intermediate.py: -------------------------------------------------------------------------------- 1 | from redengine import RedEngine 2 | from redengine.args import Return, Arg, FuncArg 3 | 4 | app = RedEngine() 5 | 6 | @app.cond('is foo') 7 | def is_foo(): 8 | "This is a custom condition" 9 | ... 10 | return True 11 | 12 | 13 | @app.task('daily & is foo', execution="process") 14 | def do_daily(): 15 | "This task runs once a day and runs on separate process" 16 | ... 17 | return ... 18 | 19 | @app.task("after task 'do_daily'") 20 | def do_after(arg1=Return('do_daily')): 21 | """This task runs after 'do_daily' and it has its the 22 | return argument as an input""" 23 | ... 24 | 25 | 26 | if __name__ == "__main__": 27 | app.run() -------------------------------------------------------------------------------- /docs/code/demos/minimal.py: -------------------------------------------------------------------------------- 1 | from redengine import RedEngine 2 | 3 | app = RedEngine() 4 | 5 | @app.task('daily') 6 | def do_things(): 7 | ... 8 | 9 | if __name__ == "__main__": 10 | app.run() -------------------------------------------------------------------------------- /docs/code/demos/monitor.py: -------------------------------------------------------------------------------- 1 | from redengine import RedEngine 2 | from redengine.args import Arg 3 | from redmail import EmailSender 4 | 5 | app = RedEngine() 6 | app.params(receivers=['me@example.com']) 7 | email = EmailSender( 8 | host="smtp.myserver.com", port=584, 9 | username="me@example.com", password="" 10 | ) 11 | 12 | @app.task('hourly') 13 | def measure_performance(receivers): 14 | email.send( 15 | subject="Wake up", 16 | ) 17 | 18 | @app.task('daily between 10:00 and 12:00') 19 | def eat_lunch(receivers): 20 | email.send( 21 | subject="Go to eat", 22 | ) 23 | 24 | @app.task('daily between 22:00 and 04:00') 25 | def go_to_sleep(receivers): 26 | email.send( 27 | subject="Go to eat", 28 | ) 29 | 30 | if __name__ == "__main__": 31 | app.run() -------------------------------------------------------------------------------- /docs/code/execution.py: -------------------------------------------------------------------------------- 1 | @app.task("daily", execution="main") 2 | def do_main(): 3 | ... 4 | 5 | @app.task("daily", execution="thread") 6 | def do_thread(): 7 | ... 8 | 9 | @app.task("daily", execution="process") 10 | def do_process(): 11 | ... -------------------------------------------------------------------------------- /docs/code/parameter/parameters.py: -------------------------------------------------------------------------------- 1 | from redengine import RedEngine 2 | from redengine.args import Arg, Return, FuncArg 3 | 4 | app = RedEngine() 5 | app.params(my_arg='hello') 6 | 7 | @app.task("every 10 seconds") 8 | def do_things(arg=Arg('my_arg')): 9 | ... 10 | # Argument 'arg' has value 'hello' 11 | assert arg == 'hello' 12 | return 'stuff' 13 | 14 | @app.task("after task 'do_things'") 15 | def do_with_return(arg=Return('do_things')): 16 | ... 17 | # Argument 'arg' is the return value of the task 'do_things' 18 | assert arg == 'stuff' 19 | 20 | @app.task("after task 'do_things'") 21 | def do_with_funcarg(arg=FuncArg(lambda: 'hello world')): 22 | ... 23 | # Argument 'arg' is the return value of the task 'do_things' 24 | assert arg == 'stuff' 25 | 26 | if __name__ == "__main__": 27 | app.run() -------------------------------------------------------------------------------- /docs/code/parameter/pipelining.py: -------------------------------------------------------------------------------- 1 | from redengine.args import Return 2 | 3 | @app.task("every 10 seconds") 4 | def do_things(): 5 | ... 6 | return 'hello' 7 | 8 | @app.task("after task 'do_things'") 9 | def do_after(arg=Return('do_things')): 10 | ... 11 | assert arg == 'hello' 12 | return 'world' 13 | 14 | @app.task("after task 'do_things', 'do_stuff'") 15 | def do_after_all(arg1=Return('do_things'), arg2=Return('do_stuff')): 16 | ... 17 | assert arg1 == 'hello' 18 | assert arg2 == 'world' 19 | -------------------------------------------------------------------------------- /docs/code/schedule/fixed_period.py: -------------------------------------------------------------------------------- 1 | @app.task('daily') 2 | def do_daily(): 3 | ... 4 | 5 | @app.task('weekly') 6 | def do_weekly(): 7 | ... 8 | 9 | @app.task('monthly') 10 | def do_monthly(): 11 | ... -------------------------------------------------------------------------------- /docs/code/schedule/fixed_period_with_args.py: -------------------------------------------------------------------------------- 1 | @app.task('daily after 10:00') 2 | def do_daily_after(): 3 | ... 4 | 5 | @app.task('daily before 22:00') 6 | def do_daily_after(): 7 | ... 8 | 9 | @app.task('daily between 10:00 and 22:00') 10 | def do_daily_between(): 11 | ... 12 | 13 | 14 | @app.task('weekly on Monday') 15 | def do_on_monday(): 16 | ... 17 | 18 | @app.task('weekly between Saturday and Sunday') 19 | def do_on_weekend(): 20 | ... 21 | 22 | 23 | @app.task('monthy after 5th') 24 | def do_monthly_after_fifth(): 25 | ... 26 | 27 | @app.task('monthy before 5th') 28 | def do_monthly_before_fifth(): 29 | ... -------------------------------------------------------------------------------- /docs/code/schedule/logic.py: -------------------------------------------------------------------------------- 1 | @app.task('true & false') 2 | def do_never(): 3 | ... 4 | 5 | @app.task('true | false') 6 | def do_constantly(): 7 | ... 8 | 9 | @app.task('~false') 10 | def do_constantly_2(): 11 | ... -------------------------------------------------------------------------------- /docs/code/schedule/time_of.py: -------------------------------------------------------------------------------- 1 | @app.task('every 10 seconds') 2 | def do_constantly(): 3 | ... 4 | 5 | @app.task('every 1 minute') 6 | def do_minutely(): 7 | ... 8 | 9 | @app.task('every 1 hour') 10 | def do_hourly(): 11 | ... 12 | 13 | @app.task('every 1 day') 14 | def do_daily(): 15 | ... 16 | 17 | @app.task('every 2 days 2 hours 20 seconds') 18 | def do_custom(): 19 | ... -------------------------------------------------------------------------------- /docs/code/snippets/parallelization.py: -------------------------------------------------------------------------------- 1 | @app.task("daily", execution="main") 2 | def do_unparallel(): 3 | ... 4 | 5 | @app.task("daily", execution="thread") 6 | def do_on_separate_thread(): 7 | ... 8 | 9 | @app.task("daily", execution="process") 10 | def do_on_separate_process(): 11 | ... -------------------------------------------------------------------------------- /docs/code/snippets/parametrize.py: -------------------------------------------------------------------------------- 1 | from redengine.args import Arg 2 | 3 | @app.param('my_param') 4 | def get_my_param(): 5 | "Get a session level parameter" 6 | return 'Hello world' 7 | 8 | @app.task("daily") 9 | def do_with_param(arg=Arg('my_param')): 10 | # 'arg' 11 | assert arg == 'Hello world' 12 | ... 13 | -------------------------------------------------------------------------------- /docs/code/snippets/pipeline.py: -------------------------------------------------------------------------------- 1 | from redengine.args import Return 2 | 3 | @app.task("daily after 07:00") 4 | def do_first(): 5 | ... 6 | return 'Hello World' 7 | 8 | @app.task("after task 'do_first'") 9 | def do_second(arg=Return('do_first')): 10 | # arg contains the value of the task do_first's return 11 | ... 12 | return 'Hello Python' 13 | -------------------------------------------------------------------------------- /docs/code/snippets/scheduling.py: -------------------------------------------------------------------------------- 1 | @app.task("every 10 seconds") 2 | def do_continuously(): 3 | ... 4 | 5 | @app.task("daily after 07:00") 6 | def do_daily_after_seven(): 7 | ... 8 | 9 | @app.task("hourly & time of day between 22:00 and 06:00") 10 | def do_hourly_at_night(): 11 | ... 12 | 13 | @app.task("(weekly on Monday | weekly on Saturday) & time of day after 10:00") 14 | def do_twice_a_week_after_ten(): 15 | ... -------------------------------------------------------------------------------- /docs/condition_syntax/dependence.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _cond-dependence: 3 | 4 | Task Dependence 5 | --------------- 6 | 7 | **Syntax** 8 | 9 | .. code-block:: none 10 | 11 | after task '' 12 | after task '' [succeeded | failed | finished | terminated] 13 | after tasks '', '' ... 14 | after tasks '', '' ... [succeeded | failed | finished] 15 | after any tasks '', '' ... [succeeded | failed | finished] 16 | 17 | **True when** 18 | 19 | True if the assigned task has not run after the given task has 20 | succeeded/failed/finished/terminated. Useful for creating 21 | task pipelines. 22 | 23 | .. note:: 24 | 25 | Must be assigned to a task. 26 | 27 | 28 | **Examples** 29 | 30 | .. code-block:: python 31 | 32 | # Creating a dummy task 33 | @app.task() 34 | def a_task(): 35 | ... 36 | 37 | # Examples 38 | app.task("after task 'a_task'") 39 | app.task("after task 'a_task' succeeded") 40 | app.task("after task 'a_task' failed") 41 | app.task("after task 'a_task' finished") 42 | app.task("after tasks 'a_task', 'another_task' finished") -------------------------------------------------------------------------------- /docs/condition_syntax/execution.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _cond-execution: 3 | 4 | Execution on fixed time interval 5 | -------------------------------- 6 | 7 | **Syntax** 8 | 9 | .. code-block:: none 10 | 11 | [hourly | daily | weekly | monthly] 12 | [hourly | daily | weekly | monthly] between and 13 | [hourly | daily | weekly | monthly] [before | after | starting]