├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── documentation_improvement.md │ └── feature_request.md └── workflows │ ├── ci_debug.yml │ ├── main.yml │ ├── release.yaml │ ├── test_cov.yml │ ├── test_docs.yml │ └── test_pr.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── Contributors.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── docs ├── Makefile ├── _static │ ├── css │ │ ├── code.css │ │ ├── colors.css │ │ └── types.css │ └── logo.png ├── code │ ├── conds │ │ ├── api │ │ │ ├── cron.py │ │ │ ├── cron_kwargs.py │ │ │ ├── crontime.py │ │ │ ├── crontime_kwargs.py │ │ │ ├── every.py │ │ │ ├── logic.py │ │ │ ├── periodical.py │ │ │ ├── periodical_restricted.py │ │ │ ├── pipe_multiple.py │ │ │ ├── pipe_single.py │ │ │ ├── pipe_with_return.py │ │ │ ├── scheduler_cycles.py │ │ │ ├── scheduler_running.py │ │ │ ├── simple.py │ │ │ ├── task_running.py │ │ │ ├── task_running_multi.py │ │ │ ├── task_status.py │ │ │ └── time_of.py │ │ └── syntax │ │ │ ├── every.py │ │ │ ├── logic.py │ │ │ ├── periodical.py │ │ │ ├── periodical_restricted.py │ │ │ ├── pipe_multiple.py │ │ │ ├── pipe_single.py │ │ │ ├── pipe_with_return.py │ │ │ ├── simple.py │ │ │ └── time_of.py │ ├── demo.py │ ├── demo_basic.py │ ├── demos │ │ ├── advanced.py │ │ ├── basic.py │ │ ├── fast_api │ │ │ ├── api.py │ │ │ ├── main.py │ │ │ └── scheduler.py │ │ ├── intermediate.py │ │ ├── minimal.py │ │ ├── minimal_async.py │ │ ├── minimal_with_api.py │ │ └── monitor.py │ ├── execution.py │ ├── naming.py │ ├── parameter │ │ ├── parameters.py │ │ └── pipelining.py │ ├── params │ │ └── return.py │ └── snippets │ │ ├── custom_condition.py │ │ ├── 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 ├── cookbook │ ├── bigger_applications.rst │ ├── conditions.rst │ ├── controlling_runtime.rst │ ├── django.rst │ ├── fastapi.rst │ ├── index.rst │ ├── robust_applications.rst │ ├── settings.rst │ └── testing.rst ├── examples │ └── index.rst ├── favicon.ico ├── handbooks │ ├── arguments.rst │ ├── conditions │ │ ├── api │ │ │ ├── cron.rst │ │ │ ├── index.rst │ │ │ ├── logical.rst │ │ │ ├── periodical.rst │ │ │ ├── pipeline.rst │ │ │ ├── scheduler.rst │ │ │ └── task_status.rst │ │ ├── classes │ │ │ └── index.rst │ │ ├── comparisons.rst │ │ ├── index.rst │ │ └── syntax │ │ │ ├── index.rst │ │ │ ├── logical.rst │ │ │ ├── periodical.rst │ │ │ └── pipeline.rst │ ├── config.rst │ ├── index.rst │ ├── logging.rst │ ├── parameterization.rst │ ├── structure.rst │ └── task │ │ ├── execution.rst │ │ ├── index.rst │ │ ├── observer.rst │ │ └── termination.rst ├── header.html ├── how_it_works.rst ├── index.rst ├── logo.svg ├── make.bat ├── rocketry_vs_alternatives.rst ├── s5defs.txt ├── scheduling.png ├── task_execution.png ├── tutorial │ ├── advanced.rst │ ├── basic.rst │ ├── index.rst │ ├── intermediate.rst │ └── quick_start.rst └── versions.rst ├── pyproject.toml ├── requirements.txt ├── requirements ├── build.txt ├── ci.txt ├── coverage.txt └── docs.txt ├── rocketry ├── __init__.py ├── _base.py ├── _setup.py ├── application.py ├── args │ ├── __init__.py │ ├── builtin.py │ └── secret.py ├── conditions │ ├── __init__.py │ ├── api.py │ ├── func.py │ ├── meta.py │ ├── parameter.py │ ├── scheduler.py │ ├── task │ │ ├── __init__.py │ │ ├── task.py │ │ └── utils.py │ └── time.py ├── conds │ └── __init__.py ├── core │ ├── __init__.py │ ├── condition │ │ ├── __init__.py │ │ └── base.py │ ├── hook.py │ ├── log │ │ ├── __init__.py │ │ └── adapter.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 │ └── utils.py ├── parameters │ ├── __init__.py │ └── func.py ├── parse │ ├── __init__.py │ ├── _condition │ │ ├── __init__.py │ │ ├── condition_item.py │ │ └── string.py │ ├── _setup_cond_parsers.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 │ └── time │ │ ├── __init__.py │ │ ├── convert.py │ │ └── interval.py ├── session.py ├── tasks │ ├── __init__.py │ ├── code.py │ ├── command.py │ ├── func.py │ ├── maintain │ │ ├── __init__.py │ │ └── os.py │ └── run_id.py ├── test │ ├── __init__.py │ ├── app │ │ ├── __init__.py │ │ ├── test_app.py │ │ ├── test_cond_api.py │ │ ├── test_custom.py │ │ ├── test_deprecated.py │ │ ├── test_grouper.py │ │ └── test_hooks.py │ ├── args │ │ ├── __init__.py │ │ ├── test_args.py │ │ └── test_core.py │ ├── condition │ │ ├── __init__.py │ │ ├── task │ │ │ ├── __init__.py │ │ │ ├── test_basic.py │ │ │ ├── test_compare.py │ │ │ ├── test_retry.py │ │ │ ├── test_time.py │ │ │ ├── test_time_executable.py │ │ │ ├── test_time_optimized.py │ │ │ └── test_time_runnable.py │ │ ├── test_alchemy.py │ │ ├── test_api.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 │ │ └── test_timezone.py │ ├── conftest.py │ ├── helpers │ │ ├── __init__.py │ │ ├── io_helpers.py │ │ ├── log_helpers.py │ │ └── task_helpers.py │ ├── log │ │ ├── __init__.py │ │ └── test_repo.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 │ │ ├── test_convert.py │ │ └── test_interval.py │ ├── pytest.ini │ ├── schedule │ │ ├── __init__.py │ │ ├── process │ │ │ ├── __init__.py │ │ │ └── test_core.py │ │ ├── test_conditions.py │ │ ├── test_core.py │ │ ├── test_failure.py │ │ ├── test_from_scripts.py │ │ ├── test_methods.py │ │ ├── test_multilaunch.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_params_order.py │ │ │ └── test_return.py │ │ ├── test_config.py │ │ ├── test_construct.py │ │ ├── test_control.py │ │ ├── test_control_task.py │ │ ├── test_core.py │ │ ├── test_deprecate.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_adapter.py │ ├── test_build.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 │ ├── test_testing.py │ └── time │ │ ├── __init__.py │ │ ├── delta │ │ ├── __init__.py │ │ ├── span │ │ │ ├── __init__.py │ │ │ ├── test_construct.py │ │ │ ├── test_contains.py │ │ │ └── test_roll.py │ │ ├── test_construct.py │ │ ├── test_contains.py │ │ └── test_roll.py │ │ ├── interval │ │ ├── __init__.py │ │ ├── test_construct.py │ │ ├── test_contains.py │ │ ├── test_core.py │ │ ├── test_relative_day.py │ │ ├── test_roll.py │ │ └── timeofweek │ │ │ ├── __init__.py │ │ │ └── test_core.py │ │ ├── logic │ │ ├── __init__.py │ │ ├── test_construct.py │ │ ├── test_in.py │ │ └── test_roll.py │ │ ├── test_contains.py │ │ ├── test_core.py │ │ ├── test_cron.py │ │ ├── test_parse.py │ │ ├── test_skip.py │ │ └── test_static.py ├── testing │ ├── __init__.py │ └── log.py ├── time │ ├── __init__.py │ ├── construct.py │ ├── cron.py │ ├── delta.py │ └── interval.py └── utils │ ├── __init__.py │ └── dependencies.py ├── setup.cfg ├── setup.py └── tox.ini /.gitattributes: -------------------------------------------------------------------------------- 1 | rocketry/_version.py export-subst 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: Miksus 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: BUG 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Screenshots** 20 | If applicable, add screenshots to help explain your problem. 21 | 22 | **Desktop (please complete the following information):** 23 | - OS: [e.g. iOS] 24 | - Python version [e.g. python 3.8] 25 | 26 | **Additional context** 27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation_improvement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation improvement 3 | about: Suggest improvement for this project's documentation 4 | title: DOCS 5 | labels: documentation 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is it corrected in the latest version (master branch)?** 11 | Yes/no 12 | 13 | Latest version of the docs: https://rocketry.readthedocs.io/en/latest/ 14 | 15 | **Location in the documentation you wish to improve** 16 | Paste the URL, ie. https://rocketry.readthedocs.io/en/latest/tutorial/quick_start.html#installing 17 | 18 | **Describe the problem** 19 | Describe what is unclear, where is a typo or what should be changed. 20 | 21 | **Suggestion for the fix** 22 | Please explain the suggested fix. 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: ENH 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci_debug.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Debug CI 4 | 5 | # Controls when the workflow will run 6 | on: 7 | 8 | # Allows you to run this workflow manually from the Actions tab 9 | workflow_dispatch: 10 | 11 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 12 | jobs: 13 | 14 | run-tests: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | timeout-minutes: 10 18 | 19 | strategy: 20 | matrix: 21 | python-version: [3.8.x] 22 | 23 | # Steps represent a sequence of tasks that will be executed as part of the job 24 | steps: 25 | - name: Checkout master 26 | uses: actions/checkout@v2 27 | with: 28 | ref: 'test/debug_ci' 29 | 30 | - name: Setup Python 31 | uses: actions/setup-python@v2 32 | with: 33 | python-version: ${{ matrix.python }} 34 | 35 | - name: Install dependencies 36 | run: | 37 | python -m pip install --upgrade pip 38 | python -m pip install -r requirements.txt 39 | python -m pip install -r requirements/ci.txt 40 | python -m pip install -e . 41 | 42 | - name: Run test suite 43 | run: | 44 | python -m pytest --pyargs redengine 45 | 46 | # Seems there is a possible problem with pytest-cov parallelization 47 | #- name: Run test suite 48 | # run: | 49 | # python -m pytest --pyargs redengine --cov-report=xml --cov-config=.coveragerc 50 | 51 | #- name: Upload test coverage 52 | # uses: codecov/codecov-action@v2 53 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Build 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: master 10 | pull_request: 11 | branches: master 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | 19 | run-tests: 20 | # The type of runner that the job will run on 21 | runs-on: ubuntu-latest 22 | timeout-minutes: 10 23 | 24 | strategy: 25 | matrix: 26 | python-version: [3.7.x, 3.8.x, 3.10.x, 3.11.x] 27 | 28 | # Steps represent a sequence of tasks that will be executed as part of the job 29 | steps: 30 | - name: Checkout master 31 | uses: actions/checkout@v2 32 | 33 | - name: Setup Python 34 | uses: actions/setup-python@v2 35 | with: 36 | python-version: ${{ matrix.python-version }} 37 | 38 | - name: Install dependencies 39 | run: | 40 | python -m pip install --upgrade pip 41 | python -m pip install .[test] 42 | 43 | - name: Run test suite 44 | working-directory: ./requirements 45 | run: | 46 | python -m pytest --pyargs rocketry -W error::UserWarning -W error::FutureWarning -W error::DeprecationWarning 47 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | # (tagged versions to PyPI, commits to TestPyPI) 3 | 4 | on: 5 | # Triggers the workflow on push events but only for the master branch 6 | push: 7 | branches: master 8 | tags: 9 | - '*' 10 | 11 | jobs: 12 | build-n-publish: 13 | name: Build and publish Python distributions to PyPI and TestPyPI 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@master 18 | with: 19 | fetch-depth: 0 20 | - name: Set up Python 3.10 21 | uses: actions/setup-python@v3 22 | with: 23 | python-version: "3.10" 24 | - name: Install pypa/build 25 | run: >- 26 | python -m 27 | pip install 28 | build 29 | --user 30 | - name: Build a binary wheel and a source tarball 31 | run: >- 32 | python -m 33 | build 34 | --sdist 35 | --wheel 36 | --outdir dist/ 37 | . 38 | - name: Publish distribution to Test PyPI 39 | uses: pypa/gh-action-pypi-publish@release/v1 40 | with: 41 | password: ${{ secrets.TEST_PYPI_API_TOKEN }} 42 | repository_url: https://test.pypi.org/legacy/ 43 | skip_existing: true 44 | - name: Publish distribution to PyPI 45 | if: startsWith(github.ref, 'refs/tags') 46 | uses: pypa/gh-action-pypi-publish@release/v1 47 | with: 48 | password: ${{ secrets.PYPI_API_TOKEN }} 49 | -------------------------------------------------------------------------------- /.github/workflows/test_cov.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Coverage 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | push: 9 | branches: master 10 | pull_request: 11 | branches: master 12 | 13 | # Allows you to run this workflow manually from the Actions tab 14 | workflow_dispatch: 15 | 16 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 17 | jobs: 18 | 19 | run-codecov: 20 | runs-on: ubuntu-latest 21 | timeout-minutes: 10 22 | 23 | strategy: 24 | matrix: 25 | python-version: [3.8.x] 26 | 27 | steps: 28 | - name: Checkout master 29 | uses: actions/checkout@v2 30 | 31 | - name: Setup Python 32 | uses: actions/setup-python@v2 33 | with: 34 | python-version: ${{ matrix.python }} 35 | 36 | - name: Install dependencies 37 | run: | 38 | python -m pip install --upgrade pip 39 | python -m pip install -r requirements/coverage.txt 40 | 41 | - name: Run test suite 42 | run: | 43 | python -m pytest --cov=rocketry --cov-report=xml rocketry/test --no-build 44 | 45 | - name: Upload test coverage 46 | uses: codecov/codecov-action@v2 47 | -------------------------------------------------------------------------------- /.github/workflows/test_docs.yml: -------------------------------------------------------------------------------- 1 | name: Doctest 2 | 3 | # Controls when the workflow will run 4 | on: 5 | # Triggers the workflow on push or pull request events but only for the master branch 6 | push: 7 | branches: master 8 | pull_request: 9 | branches: master 10 | 11 | # Allows you to run this workflow manually from the Actions tab 12 | workflow_dispatch: 13 | 14 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 15 | jobs: 16 | 17 | run-codecov: 18 | runs-on: ubuntu-latest 19 | timeout-minutes: 10 20 | 21 | strategy: 22 | matrix: 23 | python-version: [3.8.x] 24 | 25 | steps: 26 | - name: Checkout master 27 | uses: actions/checkout@v2 28 | 29 | - name: Setup Python 30 | uses: actions/setup-python@v2 31 | with: 32 | python-version: ${{ matrix.python }} 33 | 34 | - name: Install dependencies 35 | run: | 36 | python -m pip install --upgrade pip 37 | python -m pip install -r requirements/docs.txt 38 | 39 | - name: Build docs and run doctests 40 | run: | 41 | python -m sphinx docs "docs/_build/html" --color -W -bhtml 42 | python -m sphinx -b doctest docs "docs/_build/html" 43 | 44 | -------------------------------------------------------------------------------- /.github/workflows/test_pr.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: PR-test 4 | 5 | # Controls when the workflow will run 6 | on: 7 | # Triggers the workflow on push or pull request events but only for the master branch 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 13 | jobs: 14 | 15 | run-tests: 16 | # The type of runner that the job will run on 17 | runs-on: ubuntu-latest 18 | timeout-minutes: 10 19 | 20 | strategy: 21 | matrix: 22 | python-version: [3.6.x, 3.8.x, 3.10.x] 23 | 24 | # Steps represent a sequence of tasks that will be executed as part of the job 25 | steps: 26 | - name: Setup Python 27 | uses: actions/setup-python@v2 28 | with: 29 | python-version: ${{ matrix.python }} 30 | 31 | - name: Install dependencies 32 | run: | 33 | python -m pip install --upgrade pip 34 | python -m pip install -r requirements.txt 35 | python -m pip install -r requirements/ci.txt 36 | python -m pip install -e . 37 | 38 | - name: Run test suite 39 | run: | 40 | python -m pytest --pyargs rocketry 41 | 42 | # Seems there is a possible problem with pytest-cov parallelization 43 | #- name: Run test suite 44 | # run: | 45 | # python -m pytest --pyargs redengine --cov-report=xml --cov-config=.coveragerc 46 | 47 | #- name: Upload test coverage 48 | # uses: codecov/codecov-action@v2 49 | -------------------------------------------------------------------------------- /.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 | _version.py 12 | 13 | # Jupyter Notebook 14 | .ipynb_checkpoints 15 | prototype* 16 | 17 | # Environments 18 | .env 19 | .venv 20 | env/ 21 | env_linux/ 22 | venv/ 23 | ENV/ 24 | env.bak/ 25 | venv.bak/ 26 | 27 | # IDE 28 | .vscode/ 29 | .idea/ 30 | 31 | # Testing 32 | .pytest_cache/ 33 | 34 | # Private dumps 35 | proto/ 36 | draft/ 37 | private/ 38 | 39 | # Data & logs 40 | *.csv 41 | *.dat 42 | *.db 43 | 44 | # Private configurations 45 | private.yaml 46 | 47 | # Some other random stuff 48 | bash.exe.stackdump 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # tox 54 | .tox/ 55 | 56 | # Coverage 57 | cov_data/ -------------------------------------------------------------------------------- /Contributors.md: -------------------------------------------------------------------------------- 1 | # Contributors 2 | 3 | Mikael Koli - creator of Rocketry 4 | Mark Mayo - fixes and clean up of repo with python 3 updates, pylint issues 5 | bogdan - Django cookbook -------------------------------------------------------------------------------- /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 rocketry/test/test_files/*.ipynb 2 | include rocketry/test/test_files/*.py 3 | include rocketry/config/defaults/*.json 4 | include rocketry/_session.py 5 | include rocketry/_setup.py 6 | include rocketry/_pkg.py 7 | include rocketry/_version.py 8 | recursive-include rocketry/templates * -------------------------------------------------------------------------------- /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/code.css: -------------------------------------------------------------------------------- 1 | 2 | .highlight-py .k { 3 | /*Keyword*/ 4 | color: #3f6ec6; 5 | } 6 | 7 | .highlight-py .kn { 8 | /*Keyword (import)*/ 9 | color: #3f6ec6; 10 | } 11 | 12 | .highlight-py .nn { 13 | /*Module*/ 14 | color: #a846b9; 15 | } 16 | 17 | .highlight-py .nd { 18 | /*Decorator*/ 19 | color: #3f6ec6; 20 | } 21 | 22 | .highlight-py .nf { 23 | /*Function name*/ 24 | color: #000000; 25 | } -------------------------------------------------------------------------------- /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/_static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miksus/rocketry/8da223c743003166f5567a017b4ba3dfb34454ef/docs/_static/logo.png -------------------------------------------------------------------------------- /docs/code/conds/api/cron.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import cron 2 | 3 | @app.task(cron('* * * * *')) 4 | def do_minutely(): 5 | ... 6 | 7 | @app.task(cron('*/2 12-18 * Oct Fri')) 8 | def do_complex(): 9 | "Run at every 2nd minute past every hour from 12 through 18 on Friday in October." 10 | ... 11 | -------------------------------------------------------------------------------- /docs/code/conds/api/cron_kwargs.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import cron 2 | 3 | @app.task(cron(minute="*/5")) 4 | def do_simple(): 5 | "Run at every 5th minute" 6 | ... 7 | 8 | 9 | @app.task(cron(minute="*/2", hour="7-18", day_of_month="1,2,3", month="Feb-Aug/2")) 10 | def do_complex(): 11 | """Run at: 12 | - Every second minute 13 | - Between 07:00 (7 a.m.) - 18:00 (6 p.m.) 14 | - On 1st, 2nd and 3rd day of month 15 | - From February to August every second month 16 | """ 17 | ... 18 | -------------------------------------------------------------------------------- /docs/code/conds/api/crontime.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import crontime 2 | 3 | @app.task(crontime('* * * * *')) 4 | def do_minutely(): 5 | ... 6 | 7 | @app.task(crontime('*/2 12-18 * Oct Fri')) 8 | def do_complex(): 9 | "Run at every 2nd minute past every hour from 12 through 18 on Friday in October." 10 | ... 11 | -------------------------------------------------------------------------------- /docs/code/conds/api/crontime_kwargs.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import crontime 2 | 3 | @app.task(crontime(minute="*/5")) 4 | def do_simple(): 5 | "Run at every 5th minute" 6 | ... 7 | 8 | 9 | @app.task(crontime(minute="*/2", hour="7-18", day_of_month="1,2,3", month="Feb-Aug/2")) 10 | def do_complex(): 11 | """Run at: 12 | - Every second minute 13 | - Between 07:00 (7 a.m.) - 18:00 (6 p.m.) 14 | - On 1st, 2nd and 3rd day of month 15 | - From February to August every second month 16 | """ 17 | ... 18 | -------------------------------------------------------------------------------- /docs/code/conds/api/every.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import every 2 | 3 | @app.task(every('10 seconds')) 4 | def do_constantly(): 5 | ... 6 | 7 | @app.task(every('1 minute')) 8 | def do_minutely(): 9 | ... 10 | 11 | @app.task(every('1 hour')) 12 | def do_hourly(): 13 | ... 14 | 15 | @app.task(every('1 day')) 16 | def do_daily(): 17 | ... 18 | 19 | @app.task(every('2 days 2 hours 20 seconds')) 20 | def do_custom(): 21 | ... 22 | -------------------------------------------------------------------------------- /docs/code/conds/api/logic.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import true, false 2 | 3 | @app.task(true) 4 | def do_constantly(): 5 | ... 6 | 7 | @app.task(false) 8 | def do_never(): 9 | ... 10 | 11 | @app.task(true & false) 12 | def do_and(): 13 | ... 14 | 15 | @app.task(true | false) 16 | def do_or(): 17 | ... 18 | 19 | @app.task(~false) 20 | def do_not(): 21 | ... 22 | 23 | @app.task((true | false) & ~(true | false)) 24 | def do_nested(): 25 | ... 26 | -------------------------------------------------------------------------------- /docs/code/conds/api/periodical.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import minutely, hourly, daily, weekly, monthly 2 | 3 | @app.task(minutely) 4 | def do_minutely(): 5 | ... 6 | 7 | @app.task(hourly) 8 | def do_hourly(): 9 | ... 10 | 11 | @app.task(daily) 12 | def do_daily(): 13 | ... 14 | 15 | @app.task(weekly) 16 | def do_weekly(): 17 | ... 18 | 19 | @app.task(monthly) 20 | def do_monthly(): 21 | ... 22 | -------------------------------------------------------------------------------- /docs/code/conds/api/periodical_restricted.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import minutely, hourly, daily, weekly, monthly 2 | 3 | @app.task(minutely.before("45")) 4 | def do_before(): 5 | ... 6 | 7 | @app.task(hourly.after("45:00")) 8 | def do_after(): 9 | ... 10 | 11 | @app.task(daily.between("08:00", "14:00")) 12 | def do_between(): 13 | ... 14 | 15 | @app.task(daily.at("11:00")) 16 | def do_at(): 17 | ... 18 | 19 | @app.task(weekly.on("Monday")) 20 | def do_on(): 21 | ... 22 | 23 | @app.task(monthly.starting("3rd")) 24 | def do_starting(): 25 | ... 26 | -------------------------------------------------------------------------------- /docs/code/conds/api/pipe_multiple.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import after_all_success, after_any_success, after_any_finish, after_any_fail 2 | 3 | @app.task() 4 | def do_a(): 5 | ... 6 | 7 | @app.task() 8 | def do_b(): 9 | ... 10 | 11 | 12 | @app.task(after_all_success(do_a, do_b)) 13 | def do_all_succeeded(): 14 | ... 15 | 16 | @app.task(after_any_success(do_a, do_b)) 17 | def do_any_succeeded(): 18 | ... 19 | 20 | @app.task(after_any_fail(do_a, do_b)) 21 | def do_any_failed(): 22 | ... 23 | 24 | @app.task(after_any_finish(do_a, do_b)) 25 | def do_any_failed_or_succeeded(): 26 | ... 27 | -------------------------------------------------------------------------------- /docs/code/conds/api/pipe_single.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import after_success, after_fail, after_finish 2 | 3 | @app.task() 4 | def do_things(): 5 | ... 6 | 7 | @app.task(after_success(do_things)) 8 | def do_after_success(): 9 | ... 10 | 11 | @app.task(after_fail(do_things)) 12 | def do_after_fail(): 13 | ... 14 | 15 | @app.task(after_finish(do_things)) 16 | def do_after_fail_or_success(): 17 | ... 18 | -------------------------------------------------------------------------------- /docs/code/conds/api/pipe_with_return.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import daily, after_success 2 | from rocketry.args import Return 3 | 4 | @app.task(daily) 5 | def do_first(): 6 | return 'Hello World' 7 | 8 | @app.task(after_success(do_first)) 9 | def do_second(arg=Return(do_first)): 10 | # arg's value is "Hello World" 11 | ... 12 | -------------------------------------------------------------------------------- /docs/code/conds/api/scheduler_cycles.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | from rocketry.conds import scheduler_cycles 3 | 4 | app = Rocketry(config={ 5 | "shut_cond": scheduler_cycles(more_than=1) 6 | }) 7 | -------------------------------------------------------------------------------- /docs/code/conds/api/scheduler_running.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | from rocketry.conds import scheduler_running 3 | 4 | app = Rocketry(config={ 5 | "shut_cond": scheduler_running(more_than="5 minutes") 6 | }) 7 | -------------------------------------------------------------------------------- /docs/code/conds/api/simple.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import ( 2 | every, hourly, daily, 3 | after_success, 4 | true, false 5 | ) 6 | 7 | @app.task(every('10 seconds')) 8 | def do_constantly(): 9 | ... 10 | 11 | @app.task(hourly) 12 | def do_hourly(): 13 | ... 14 | 15 | @app.task(daily.between('08:00', '14:00')) 16 | def do_daily(): 17 | ... 18 | 19 | @app.task(after_success(do_daily)) 20 | def do_after(): 21 | ... 22 | 23 | @app.task(true & false & ~(true | false)) 24 | def do_logic(): 25 | ... 26 | -------------------------------------------------------------------------------- /docs/code/conds/api/task_running.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import running 2 | 3 | @app.task(end_cond=running.more_than("2 mins")) 4 | def do_things(): 5 | ... # Terminates if runs over 2 minutes 6 | 7 | @app.task(running(do_things)) 8 | def do_if_runs(): 9 | ... # Starts if do_things is running 10 | 11 | @app.task(running(do_things).less_than("2 mins")) 12 | def do_if_runs_less_than(): 13 | ... # Starts if do_things is running less than 2 mins 14 | 15 | @app.task(running(do_things).between("2 mins", "5 mins")) 16 | def do_if_runs_between(): 17 | ... 18 | # Starts if do_things is running 19 | # less than 2 mins but no more than 5 minutes 20 | -------------------------------------------------------------------------------- /docs/code/conds/api/task_running_multi.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import running 2 | 3 | @app.task(running <= 4, multilanch=True) 4 | def do_parallel_limited(): 5 | ... # Allows 4 parallel runs 6 | 7 | @app.task(~running, multilanch=True) 8 | def do_non_parallel(): 9 | ... # Allows no parallel runs 10 | 11 | @app.task(running(do_parallel_limited) >= 2) 12 | def do_if_runs_parallel(): 13 | ... # Runs if the other has at least two parallel runs 14 | -------------------------------------------------------------------------------- /docs/code/conds/api/task_status.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import finished, succeeded, failed 2 | 3 | @app.task() 4 | def do_things(): 5 | ... # Dummy task for demonstration 6 | 7 | @app.task(finished(task=do_things).this_hour) 8 | def do_if_finish(): 9 | ... 10 | 11 | @app.task(succeeded(task=do_things).today.between("10:00", "12:00")) 12 | def do_if_fail_between(): 13 | ... 14 | 15 | @app.task(failed.this_week.on("Monday")) 16 | def do_if_itself_fails(): 17 | ... 18 | -------------------------------------------------------------------------------- /docs/code/conds/api/time_of.py: -------------------------------------------------------------------------------- 1 | from rocketry.conds import time_of_minute, time_of_hour, time_of_day, time_of_week 2 | 3 | @app.task(time_of_minute.before("45")) 4 | def do_constantly_minute_before(): 5 | ... 6 | 7 | @app.task(time_of_hour.after("45:00")) 8 | def do_constantly_hour_after(): 9 | ... 10 | 11 | @app.task(time_of_day.between("08:00", "14:00")) 12 | def do_constantly_day_between(): 13 | ... 14 | 15 | @app.task(time_of_week.on("Monday")) 16 | def do_constantly_week_on(): 17 | ... 18 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/every.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 | ... 20 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/logic.py: -------------------------------------------------------------------------------- 1 | @app.task('true') 2 | def do_constantly(): 3 | ... 4 | 5 | @app.task('false') 6 | def do_never(): 7 | ... 8 | 9 | @app.task('true & false') 10 | def do_and(): 11 | ... 12 | 13 | @app.task('true | false') 14 | def do_or(): 15 | ... 16 | 17 | @app.task('~false') 18 | def do_not(): 19 | ... 20 | 21 | @app.task('(true | false) & ~(true | false)') 22 | def do_nested(): 23 | ... 24 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/periodical.py: -------------------------------------------------------------------------------- 1 | @app.task('minutely') 2 | def do_minutely(): 3 | ... 4 | 5 | @app.task('hourly') 6 | def do_hourly(): 7 | ... 8 | 9 | @app.task('daily') 10 | def do_daily(): 11 | ... 12 | 13 | @app.task('weekly') 14 | def do_weekly(): 15 | ... 16 | 17 | @app.task('monthly') 18 | def do_monthly(): 19 | ... 20 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/periodical_restricted.py: -------------------------------------------------------------------------------- 1 | @app.task("minutely before 45") 2 | def do_minutely(): 3 | ... 4 | 5 | @app.task("hourly after 45:00") 6 | def do_hourly(): 7 | ... 8 | 9 | @app.task("daily between 08:00 and 14:00") 10 | def do_daily(): 11 | ... 12 | 13 | @app.task("weekly on Monday") 14 | def do_weekly(): 15 | ... 16 | 17 | @app.task("monthly starting 3rd") 18 | def do_monthly(): 19 | ... 20 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/pipe_multiple.py: -------------------------------------------------------------------------------- 1 | @app.task() 2 | def do_a(): 3 | ... 4 | 5 | @app.task() 6 | def do_b(): 7 | ... 8 | 9 | 10 | @app.task("after tasks 'do_a', 'do_b' succeeded") 11 | def do_all_succeeded(): 12 | ... 13 | 14 | @app.task("after any tasks 'do_a', 'do_b' succeeded") 15 | def do_any_succeeded(): 16 | ... 17 | 18 | @app.task("after any tasks 'do_a', 'do_b' failed") 19 | def do_any_failed(): 20 | ... 21 | 22 | @app.task("after any tasks 'do_a', 'do_b' finished") 23 | def do_any_failed_or_succeeded(): 24 | ... 25 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/pipe_single.py: -------------------------------------------------------------------------------- 1 | @app.task() 2 | def do_things(): 3 | ... 4 | 5 | @app.task("after task 'do_things'") 6 | def do_after_success(): 7 | ... 8 | 9 | @app.task("after task 'do_things' succeeded") 10 | def do_after_success_2(): 11 | ... 12 | 13 | @app.task("after task 'do_things' failed") 14 | def do_after_fail(): 15 | ... 16 | 17 | @app.task("after task 'do_things' finished") 18 | def do_after_fail_or_success(): 19 | ... 20 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/pipe_with_return.py: -------------------------------------------------------------------------------- 1 | from rocketry.args import Return 2 | 3 | @app.task("daily") 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's value is "Hello World" 11 | ... 12 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/simple.py: -------------------------------------------------------------------------------- 1 | @app.task('every 10 seconds') 2 | def do_constantly(): 3 | ... 4 | 5 | @app.task('hourly') 6 | def do_hourly(): 7 | ... 8 | 9 | @app.task('daily between 08:00 and 14:00') 10 | def do_daily(): 11 | ... 12 | 13 | @app.task("after task 'do_daily'") 14 | def do_after(): 15 | ... 16 | 17 | @app.task('true & false & ~(true | false)') 18 | def do_logic(): 19 | ... 20 | -------------------------------------------------------------------------------- /docs/code/conds/syntax/time_of.py: -------------------------------------------------------------------------------- 1 | @app.task("time of minute before 45") 2 | def do_constantly_minute_before(): 3 | ... 4 | 5 | @app.task("time of hour after 45:00") 6 | def do_constantly_hour_after(): 7 | ... 8 | 9 | @app.task("time of day between 08:00 and 14:00") 10 | def do_constantly_day_between(): 11 | ... 12 | 13 | @app.task("time of week on Monday") 14 | def do_constantly_week_on(): 15 | ... 16 | -------------------------------------------------------------------------------- /docs/code/demo.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | from rocketry.args import Return 3 | 4 | app = Rocketry() 5 | 6 | @app.task('daily') 7 | def do_daily(): 8 | "This function runs once a day" 9 | ... 10 | 11 | 12 | @app.task('daily between 07:00 and 10:00 | daily between 16:00 and 20:00') 13 | def do_twice_a_day(): 14 | "This function runs twice a day (in the morning and in the afternoon)" 15 | # The '|' means OR operator. Fully supports logical operations. 16 | ... 17 | 18 | 19 | @app.task("after task 'do_daily'") 20 | def do_after_another(arg=Return('do_daily')): 21 | "Run after 'do_daily' task" 22 | # The parameter 'arg' has the return value of the function 'do_daily' 23 | ... 24 | 25 | 26 | if __name__ == "__main__": 27 | # Start the scheduler 28 | app.run() 29 | -------------------------------------------------------------------------------- /docs/code/demo_basic.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | 3 | app = Rocketry() 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() 15 | -------------------------------------------------------------------------------- /docs/code/demos/advanced.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | from rocketry.args import Return, Arg 3 | 4 | app = Rocketry() 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 | 52 | @app.task('(true & true) | (false & True & ~True)') 53 | def do_complex(): 54 | """Notice the logical expression in the task start condition""" 55 | 56 | 57 | if __name__ == "__main__": 58 | app.run() 59 | -------------------------------------------------------------------------------- /docs/code/demos/basic.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | 3 | app = Rocketry() 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() 15 | -------------------------------------------------------------------------------- /docs/code/demos/fast_api/main.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import uvicorn 4 | 5 | from api import app as app_fastapi 6 | from scheduler import app as app_rocketry 7 | 8 | 9 | class Server(uvicorn.Server): 10 | """Customized uvicorn.Server 11 | 12 | Uvicorn server overrides signals and we need to include 13 | Rocketry to the signals.""" 14 | def handle_exit(self, sig: int, frame) -> None: 15 | app_rocketry.session.shut_down() 16 | return super().handle_exit(sig, frame) 17 | 18 | 19 | async def main(): 20 | "Run scheduler and the API" 21 | server = Server(config=uvicorn.Config(app_fastapi, workers=1, loop="asyncio")) 22 | 23 | api = asyncio.create_task(server.serve()) 24 | sched = asyncio.create_task(app_rocketry.serve()) 25 | 26 | await asyncio.wait([sched, api]) 27 | 28 | if __name__ == "__main__": 29 | asyncio.run(main()) 30 | -------------------------------------------------------------------------------- /docs/code/demos/fast_api/scheduler.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | 3 | app = Rocketry(execution="async") 4 | 5 | @app.task('every 20 seconds') 6 | async def do_things(): 7 | ... 8 | 9 | @app.task('every 5 seconds') 10 | async def do_stuff(): 11 | ... 12 | 13 | if __name__ == "__main__": 14 | app.run() 15 | -------------------------------------------------------------------------------- /docs/code/demos/intermediate.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | from rocketry.args import Return, Session, Arg, FuncArg 3 | from rocketry.conds import daily, time_of_week, after_success 4 | 5 | app = Rocketry() 6 | 7 | @app.cond() 8 | def is_foo(): 9 | "This is a custom condition" 10 | ... 11 | return True 12 | 13 | @app.task(daily & is_foo) 14 | def do_daily(): 15 | "This task runs once a day when foo is true" 16 | ... 17 | return ... 18 | 19 | @app.task((daily.at("10:00") | daily.at("19:00")) & time_of_week.between("Mon", "Fri"), 20 | execution="process") 21 | def do_complex(): 22 | "This task runs on complex interval and on separate process" 23 | ... 24 | return ... 25 | 26 | 27 | @app.task(after_success(do_daily)) 28 | def do_after_another(arg=Return(do_daily)): 29 | """This task runs after 'do_daily' and it has its the 30 | return argument as an input""" 31 | ... 32 | 33 | @app.task(daily) 34 | def do_with_params(arg1=FuncArg(lambda: ...), arg2=Arg("myparam")): 35 | """This task runs with variety of arguments""" 36 | ... 37 | 38 | @app.task(daily, execution="thread") 39 | def do_on_session(session=Session()): 40 | "This task modifies the scheduling session" 41 | # Setting a task to run 42 | for task in session.tasks: 43 | if task.name == "do_after_another": 44 | task.run(arg="...") 45 | 46 | # Call for shut down 47 | session.shut_down() 48 | 49 | if __name__ == "__main__": 50 | app.params(myparam="...") 51 | app.run() 52 | -------------------------------------------------------------------------------- /docs/code/demos/minimal.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | 3 | app = Rocketry() 4 | 5 | @app.task('daily') 6 | def do_things(): 7 | ... 8 | 9 | if __name__ == "__main__": 10 | app.run() 11 | -------------------------------------------------------------------------------- /docs/code/demos/minimal_async.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from rocketry import Rocketry 3 | 4 | app = Rocketry(execution="async") 5 | 6 | @app.task() 7 | async def do_things(): 8 | ... 9 | 10 | async def main(): 11 | "Launch Rocketry app (and possibly something else)" 12 | rocketry_task = asyncio.create_task(app.serve()) 13 | # Start possibly other async apps 14 | await rocketry_task 15 | 16 | if __name__ == "__main__": 17 | asyncio.run(main()) 18 | -------------------------------------------------------------------------------- /docs/code/demos/minimal_with_api.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | from rocketry.conds import daily 3 | 4 | app = Rocketry() 5 | 6 | @app.task(daily) 7 | def do_things(): 8 | ... 9 | 10 | if __name__ == "__main__": 11 | app.run() 12 | -------------------------------------------------------------------------------- /docs/code/demos/monitor.py: -------------------------------------------------------------------------------- 1 | from redmail import EmailSender 2 | from rocketry import Rocketry 3 | 4 | 5 | app = Rocketry() 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() 32 | -------------------------------------------------------------------------------- /docs/code/execution.py: -------------------------------------------------------------------------------- 1 | @app.task(execution="main") 2 | def do_main(): 3 | ... 4 | 5 | @app.task(execution="async") 6 | async def do_async(): 7 | ... 8 | 9 | @app.task(execution="thread") 10 | def do_thread(): 11 | ... 12 | 13 | @app.task(execution="process") 14 | def do_process(): 15 | ... 16 | -------------------------------------------------------------------------------- /docs/code/naming.py: -------------------------------------------------------------------------------- 1 | @app.task(name="mytask") 2 | def do_things(): 3 | ... 4 | -------------------------------------------------------------------------------- /docs/code/parameter/parameters.py: -------------------------------------------------------------------------------- 1 | from rocketry import Rocketry 2 | from rocketry.args import Arg, Return, FuncArg 3 | 4 | app = Rocketry() 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() 28 | -------------------------------------------------------------------------------- /docs/code/parameter/pipelining.py: -------------------------------------------------------------------------------- 1 | from rocketry.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/params/return.py: -------------------------------------------------------------------------------- 1 | from rocketry.args import Return 2 | 3 | @app.task() 4 | def do_first(): 5 | 6 | return 'Hello World' 7 | 8 | @app.task() 9 | def do_second(arg=Return(do_first)): 10 | # arg's value is "Hello World" 11 | ... 12 | -------------------------------------------------------------------------------- /docs/code/snippets/custom_condition.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | from rocketry import Rocketry 3 | from rocketry.conds import daily 4 | 5 | app = Rocketry() 6 | 7 | @app.cond() 8 | def file_exists(file): 9 | "Custom condition that checks if file exists" 10 | return Path(file).exists() 11 | 12 | @app.task(daily & file_exists("data.csv")) 13 | def do_things(): 14 | "Task that runs once a day when data.csv exists" 15 | ... 16 | 17 | if __name__ == "__main__": 18 | app.run() 19 | -------------------------------------------------------------------------------- /docs/code/snippets/parallelization.py: -------------------------------------------------------------------------------- 1 | @app.task(execution="main") 2 | def do_unparallel(): 3 | ... 4 | 5 | @app.task(execution="async") 6 | async def do_unparallel(): 7 | ... 8 | 9 | @app.task(execution="thread") 10 | def do_on_separate_thread(): 11 | ... 12 | 13 | @app.task(execution="process") 14 | def do_on_separate_process(): 15 | ... 16 | -------------------------------------------------------------------------------- /docs/code/snippets/parametrize.py: -------------------------------------------------------------------------------- 1 | from rocketry.args import Arg, FuncArg, EnvArg, CliArg 2 | 3 | def get_value(): 4 | return 'Hello World' 5 | 6 | @app.param('my_param') 7 | def get_session_param(): 8 | "Session level parameter (named as 'my_param')" 9 | return 'Hello Python' 10 | 11 | @app.task() 12 | def do_with_param(arg1=Arg('my_param'), arg2=FuncArg(get_value), 13 | arg3=EnvArg('ENV_VARIABLE'), arg4=CliArg('--cli_arg')): 14 | ... 15 | -------------------------------------------------------------------------------- /docs/code/snippets/pipeline.py: -------------------------------------------------------------------------------- 1 | from rocketry.args import Return 2 | from rocketry.conds import daily, after_success 3 | 4 | @app.task(daily) 5 | def do_first(): 6 | 7 | return 'Hello World' 8 | 9 | @app.task(after_success(do_first)) 10 | def do_second(arg=Return(do_first)): 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 | ... 16 | -------------------------------------------------------------------------------- /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]