├── .bumpversion.cfg ├── .cookiecutterrc ├── .coveragerc ├── .editorconfig ├── .github ├── FUNDING.yml ├── dependabot.yml ├── opencollective.yml ├── tidelift.yml └── workflows │ ├── codeql-analysis.yml │ ├── linter.yml │ ├── python-package.yml │ └── semgrep.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── AUTHORS ├── Changelog.rst ├── FAQ ├── INSTALL ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.rst ├── SECURITY.md ├── THANKS ├── TODO ├── conftest.py ├── docs ├── Makefile ├── _ext │ └── .keep ├── _static │ └── .keep ├── _templates │ └── sidebardonations.html ├── changelog.rst ├── conf.py ├── faq.rst ├── images │ ├── favicon.ico │ ├── kombu.jpg │ └── kombusmall.jpg ├── includes │ ├── installation.txt │ ├── introduction.txt │ └── resources.txt ├── index.rst ├── introduction.rst ├── make.bat ├── reference │ ├── index.rst │ ├── kombu.abstract.rst │ ├── kombu.asynchronous.aws.connection.rst │ ├── kombu.asynchronous.aws.rst │ ├── kombu.asynchronous.aws.sqs.connection.rst │ ├── kombu.asynchronous.aws.sqs.message.rst │ ├── kombu.asynchronous.aws.sqs.queue.rst │ ├── kombu.asynchronous.aws.sqs.rst │ ├── kombu.asynchronous.debug.rst │ ├── kombu.asynchronous.http.base.rst │ ├── kombu.asynchronous.http.curl.rst │ ├── kombu.asynchronous.http.rst │ ├── kombu.asynchronous.http.urllib3_client.rst │ ├── kombu.asynchronous.hub.rst │ ├── kombu.asynchronous.rst │ ├── kombu.asynchronous.semaphore.rst │ ├── kombu.asynchronous.timer.rst │ ├── kombu.clocks.rst │ ├── kombu.common.rst │ ├── kombu.compat.rst │ ├── kombu.compression.rst │ ├── kombu.connection.rst │ ├── kombu.exceptions.rst │ ├── kombu.log.rst │ ├── kombu.matcher.rst │ ├── kombu.message.rst │ ├── kombu.mixins.rst │ ├── kombu.pidbox.rst │ ├── kombu.pools.rst │ ├── kombu.resource.rst │ ├── kombu.rst │ ├── kombu.serialization.rst │ ├── kombu.simple.rst │ ├── kombu.transport.SLMQ.rst │ ├── kombu.transport.SQS.rst │ ├── kombu.transport.azureservicebus.rst │ ├── kombu.transport.azurestoragequeues.rst │ ├── kombu.transport.base.rst │ ├── kombu.transport.confluentkafka.rst │ ├── kombu.transport.consul.rst │ ├── kombu.transport.etcd.rst │ ├── kombu.transport.filesystem.rst │ ├── kombu.transport.gcpubsub.rst │ ├── kombu.transport.librabbitmq.rst │ ├── kombu.transport.memory.rst │ ├── kombu.transport.mongodb.rst │ ├── kombu.transport.native_delayed_delivery.rst │ ├── kombu.transport.pyamqp.rst │ ├── kombu.transport.pyro.rst │ ├── kombu.transport.qpid.rst │ ├── kombu.transport.redis.rst │ ├── kombu.transport.rst │ ├── kombu.transport.sqlalchemy.rst │ ├── kombu.transport.virtual.exchange.rst │ ├── kombu.transport.virtual.rst │ ├── kombu.transport.zookeeper.rst │ ├── kombu.utils.amq_manager.rst │ ├── kombu.utils.collections.rst │ ├── kombu.utils.compat.rst │ ├── kombu.utils.debug.rst │ ├── kombu.utils.div.rst │ ├── kombu.utils.encoding.rst │ ├── kombu.utils.eventio.rst │ ├── kombu.utils.functional.rst │ ├── kombu.utils.imports.rst │ ├── kombu.utils.json.rst │ ├── kombu.utils.limits.rst │ ├── kombu.utils.objects.rst │ ├── kombu.utils.scheduling.rst │ ├── kombu.utils.text.rst │ ├── kombu.utils.time.rst │ ├── kombu.utils.url.rst │ └── kombu.utils.uuid.rst ├── templates │ └── readme.txt └── userguide │ ├── connections.rst │ ├── consumers.rst │ ├── examples.rst │ ├── failover.rst │ ├── index.rst │ ├── introduction.rst │ ├── pools.rst │ ├── producers.rst │ ├── serialization.rst │ └── simple.rst ├── examples ├── complete_receive.py ├── complete_send.py ├── delayed_infra.py ├── experimental │ └── async_consume.py ├── hello_consumer.py ├── hello_publisher.py ├── memory_transport.py ├── rpc-tut6 │ ├── rpc_client.py │ └── rpc_server.py ├── simple_eventlet_receive.py ├── simple_eventlet_send.py ├── simple_receive.py ├── simple_send.py └── simple_task_queue │ ├── __init__.py │ ├── client.py │ ├── queues.py │ ├── tasks.py │ └── worker.py ├── kombu ├── __init__.py ├── abstract.py ├── asynchronous │ ├── __init__.py │ ├── aws │ │ ├── __init__.py │ │ ├── connection.py │ │ ├── ext.py │ │ └── sqs │ │ │ ├── __init__.py │ │ │ ├── connection.py │ │ │ ├── ext.py │ │ │ ├── message.py │ │ │ └── queue.py │ ├── debug.py │ ├── http │ │ ├── __init__.py │ │ ├── base.py │ │ └── urllib3_client.py │ ├── hub.py │ ├── semaphore.py │ └── timer.py ├── clocks.py ├── common.py ├── compat.py ├── compression.py ├── connection.py ├── entity.py ├── exceptions.py ├── log.py ├── matcher.py ├── message.py ├── messaging.py ├── mixins.py ├── pidbox.py ├── pools.py ├── resource.py ├── serialization.py ├── simple.py ├── transport │ ├── SLMQ.py │ ├── SQS.py │ ├── __init__.py │ ├── azureservicebus.py │ ├── azurestoragequeues.py │ ├── base.py │ ├── confluentkafka.py │ ├── consul.py │ ├── etcd.py │ ├── filesystem.py │ ├── gcpubsub.py │ ├── librabbitmq.py │ ├── memory.py │ ├── mongodb.py │ ├── native_delayed_delivery.py │ ├── pyamqp.py │ ├── pyro.py │ ├── qpid.py │ ├── redis.py │ ├── sqlalchemy │ │ ├── __init__.py │ │ └── models.py │ ├── virtual │ │ ├── __init__.py │ │ ├── base.py │ │ └── exchange.py │ └── zookeeper.py └── utils │ ├── __init__.py │ ├── amq_manager.py │ ├── collections.py │ ├── compat.py │ ├── debug.py │ ├── div.py │ ├── encoding.py │ ├── eventio.py │ ├── functional.py │ ├── imports.py │ ├── json.py │ ├── limits.py │ ├── objects.py │ ├── scheduling.py │ ├── text.py │ ├── time.py │ ├── url.py │ └── uuid.py ├── pyproject.toml ├── requirements ├── default.txt ├── dev.txt ├── docs.txt ├── extras │ ├── azureservicebus.txt │ ├── azurestoragequeues.txt │ ├── brotli.txt │ ├── confluentkafka.txt │ ├── consul.txt │ ├── couchdb.txt │ ├── etcd.txt │ ├── gcpubsub.txt │ ├── librabbitmq.txt │ ├── lzma.txt │ ├── mongodb.txt │ ├── msgpack.txt │ ├── pyro.txt │ ├── qpid.txt │ ├── redis.txt │ ├── slmq.txt │ ├── sqlalchemy.txt │ ├── sqs.txt │ ├── yaml.txt │ ├── zookeeper.txt │ └── zstd.txt ├── funtest.txt ├── pkgutils.txt ├── test-ci.txt ├── test-integration.txt └── test.txt ├── setup.cfg ├── setup.py ├── t ├── __init__.py ├── integration │ ├── __init__.py │ ├── common.py │ ├── test_kafka.py │ ├── test_mongodb.py │ ├── test_py_amqp.py │ └── test_redis.py ├── mocks.py ├── skip.py └── unit │ ├── __init__.py │ ├── asynchronous │ ├── __init__.py │ ├── aws │ │ ├── __init__.py │ │ ├── case.py │ │ ├── sqs │ │ │ ├── __init__.py │ │ │ ├── test_connection.py │ │ │ └── test_queue.py │ │ ├── test_aws.py │ │ └── test_connection.py │ ├── http │ │ ├── __init__.py │ │ ├── test_http.py │ │ └── test_urllib3.py │ ├── test_hub.py │ ├── test_semaphore.py │ └── test_timer.py │ ├── conftest.py │ ├── test_clocks.py │ ├── test_common.py │ ├── test_compat.py │ ├── test_compression.py │ ├── test_connection.py │ ├── test_entity.py │ ├── test_exceptions.py │ ├── test_log.py │ ├── test_matcher.py │ ├── test_message.py │ ├── test_messaging.py │ ├── test_mixins.py │ ├── test_pidbox.py │ ├── test_pools.py │ ├── test_serialization.py │ ├── test_simple.py │ ├── transport │ ├── __init__.py │ ├── test_SQS.py │ ├── test_azureservicebus.py │ ├── test_azurestoragequeues.py │ ├── test_base.py │ ├── test_consul.py │ ├── test_etcd.py │ ├── test_filesystem.py │ ├── test_gcpubsub.py │ ├── test_librabbitmq.py │ ├── test_memory.py │ ├── test_mongodb.py │ ├── test_native_delayed_delivery.py │ ├── test_pyamqp.py │ ├── test_pyro.py │ ├── test_qpid.py │ ├── test_redis.py │ ├── test_sqlalchemy.py │ ├── test_transport.py │ ├── test_zookeeper.py │ └── virtual │ │ ├── __init__.py │ │ ├── test_base.py │ │ └── test_exchange.py │ └── utils │ ├── __init__.py │ ├── test_amq_manager.py │ ├── test_compat.py │ ├── test_debug.py │ ├── test_div.py │ ├── test_encoding.py │ ├── test_functional.py │ ├── test_imports.py │ ├── test_json.py │ ├── test_objects.py │ ├── test_scheduling.py │ ├── test_time.py │ ├── test_url.py │ ├── test_utils.py │ └── test_uuid.py └── tox.ini /.bumpversion.cfg: -------------------------------------------------------------------------------- 1 | [bumpversion] 2 | current_version = 5.5.4 3 | commit = True 4 | tag = True 5 | parse = (?P\d+)\.(?P\d+)\.(?P\d+)(?P[a-z]+)? 6 | serialize = 7 | {major}.{minor}.{patch}{releaselevel} 8 | {major}.{minor}.{patch} 9 | 10 | [bumpversion:file:kombu/__init__.py] 11 | 12 | [bumpversion:file:docs/includes/introduction.txt] 13 | 14 | [bumpversion:file:README.rst] 15 | -------------------------------------------------------------------------------- /.cookiecutterrc: -------------------------------------------------------------------------------- 1 | default_context: 2 | 3 | email: 'ask@celeryproject.org' 4 | full_name: 'Ask Solem' 5 | github_username: 'celery' 6 | project_name: 'Kombu' 7 | project_short_description: 'Messaging library for Python.' 8 | project_slug: 'kombu' 9 | version: '1.0.0' 10 | year: '2009-2016' 11 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = 1 3 | cover_pylib = 0 4 | include=*kombu/* 5 | omit = kombu.tests.* 6 | 7 | [report] 8 | omit = 9 | */python?.?/* 10 | */site-packages/* 11 | */pypy/* 12 | *kombu/async/http/urllib3_client.py 13 | *kombu/five.py 14 | *kombu/transport/mongodb.py 15 | *kombu/transport/filesystem.py 16 | *kombu/transport/sqlalchemy/* 17 | *kombu/utils.compat.py 18 | *kombu/utils/eventio.py 19 | *kombu/async/debug.py 20 | *kombu/transport/amqplib.py 21 | *kombu/transport/couchdb.py 22 | *kombu/transport/beanstalk.py 23 | *kombu/transport/sqlalchemy.py 24 | *kombu/transport/zookeeper.py 25 | *kombu/transport/zmq.py 26 | *kombu/transport/django.py 27 | *kombu/transport/pyro.py 28 | *kombu/transport/azurestoragequeues.py 29 | *kombu/transport/qpid* 30 | exclude_lines = 31 | pragma: no cover 32 | 33 | for infinity 34 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_style = space 7 | indent_size = 4 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | charset = utf-8 11 | end_of_line = lf 12 | 13 | [Makefile] 14 | indent_style = tab 15 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | patreon: auvipy 4 | open_collective: celery 5 | ko_fi: # Replace with a single Ko-fi username 6 | tidelift: "pypi/kombu" 7 | custom: # Replace with a single custom sponsorship URL 8 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | - package-ecosystem: "pip" 8 | directory: "/" 9 | schedule: 10 | interval: "daily" 11 | -------------------------------------------------------------------------------- /.github/opencollective.yml: -------------------------------------------------------------------------------- 1 | collective: celery 2 | tiers: 3 | - tiers: '*' 4 | labels: ['Backer ❤️'] 5 | message: 'Hey . Thank you for supporting the project!:heart:' 6 | - tiers: ['Basic Sponsor', 'Sponsor', 'Silver Sponsor', 'Gold Sponsor'] 7 | labels: ['Sponsor ❤️'] 8 | message: | 9 | Thank you for sponsoring the project!:heart::heart::heart: 10 | Resolving this issue is one of our top priorities. 11 | One of @celery/core-developers will triage it shortly. 12 | invitation: | 13 | Hey :wave:, 14 | Thank you for opening an issue. We will get back to you as soon as we can. 15 | Also, check out our [Open Collective]() and consider backing us - every little helps! 16 | 17 | We also offer priority support for our sponsors. 18 | If you require immediate assistance please consider sponsoring us. 19 | -------------------------------------------------------------------------------- /.github/tidelift.yml: -------------------------------------------------------------------------------- 1 | name: Tidelift Alignment 2 | on: 3 | push: 4 | 5 | 6 | jobs: 7 | build: 8 | name: Run Tidelift to ensure approved open source packages are in use 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v3 13 | - name: Alignment 14 | uses: tidelift/alignment-action@main 15 | env: 16 | TIDELIFT_API_KEY: ${{ secrets.TIDELIFT_API_KEY }} 17 | TIDELIFT_ORGANIZATION: ${{ secrets.TIDELIFT_ORGANIZATION }} 18 | TIDELIFT_PROJECT: ${{ secrets.TIDELIFT_PROJECT }} 19 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main ] 20 | 21 | jobs: 22 | analyze: 23 | name: Analyze 24 | runs-on: blacksmith-4vcpu-ubuntu-2204 25 | permissions: 26 | actions: read 27 | contents: read 28 | security-events: write 29 | 30 | strategy: 31 | fail-fast: false 32 | matrix: 33 | language: [ 'python' ] 34 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 35 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 36 | 37 | steps: 38 | - name: Checkout repository 39 | uses: actions/checkout@v4 40 | 41 | # Initializes the CodeQL tools for scanning. 42 | - name: Initialize CodeQL 43 | uses: github/codeql-action/init@v3 44 | with: 45 | languages: ${{ matrix.language }} 46 | # If you wish to specify custom queries, you can do so here or in a config file. 47 | # By default, queries listed here will override any specified in a config file. 48 | # Prefix the list here with "+" to use these queries and those in the config file. 49 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 50 | 51 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 52 | # If this step fails, then you should remove it and run the build manually (see below) 53 | - name: Autobuild 54 | uses: github/codeql-action/autobuild@v3 55 | 56 | # ℹ️ Command-line programs to run using the OS shell. 57 | # 📚 https://git.io/JvXDl 58 | 59 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 60 | # and modify them (or add more) to build your code if your project 61 | # uses a compiled language 62 | 63 | #- run: | 64 | # make bootstrap 65 | # make release 66 | 67 | - name: Perform CodeQL Analysis 68 | uses: github/codeql-action/analyze@v3 69 | -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | name: Linter 2 | 3 | on: [pull_request, workflow_dispatch] 4 | 5 | jobs: 6 | pre-commit: 7 | runs-on: blacksmith-4vcpu-ubuntu-2204 8 | steps: 9 | 10 | - name: Checkout branch 11 | uses: actions/checkout@v4 12 | 13 | - name: Run pre-commit 14 | uses: pre-commit/action@v3.0.1 15 | 16 | lint: 17 | runs-on: blacksmith-4vcpu-ubuntu-2204 18 | strategy: 19 | matrix: 20 | python-version: ["3.13"] 21 | steps: 22 | - name: Install system packages 23 | run: sudo apt-get update && sudo apt-get install libssl-dev 24 | - name: Check out code from GitHub 25 | uses: actions/checkout@v4 26 | - name: Set up Python ${{ matrix.python-version }} 27 | id: python 28 | uses: useblacksmith/setup-python@v6 29 | with: 30 | python-version: ${{ matrix.python-version }} 31 | - name: Install dependencies 32 | run: pip install --upgrade pip wheel tox tox-docker 33 | - name: Run flake8 34 | run: tox -v -e flake8 -- -v 35 | - name: Run pydocstyle 36 | run: tox -v -e pydocstyle -- -v 37 | - name: Run apicheck 38 | run: tox -v -e apicheck -- -v 39 | - name: Run mypy 40 | run: tox -v -e mypy -- -v 41 | -------------------------------------------------------------------------------- /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: {} 3 | push: 4 | branches: 5 | - main 6 | - master 7 | paths: 8 | - .github/workflows/semgrep.yml 9 | schedule: 10 | # random HH:MM to avoid a load spike on GitHub Actions at 00:00 11 | - cron: 41 19 * * * 12 | name: Semgrep 13 | jobs: 14 | semgrep: 15 | name: Scan 16 | runs-on: blacksmith-4vcpu-ubuntu-2204 17 | env: 18 | SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} 19 | container: 20 | image: returntocorp/semgrep 21 | steps: 22 | - uses: actions/checkout@v4 23 | - run: semgrep ci 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | *$py.class 4 | *~ 5 | *.sqlite 6 | *.sqlite-journal 7 | settings_local.py 8 | build/ 9 | .build/ 10 | _build/ 11 | .*.sw* 12 | dist/ 13 | *.egg-info 14 | pip-log.txt 15 | devdatabase.db 16 | ^parts 17 | ^eggs 18 | ^bin 19 | developer-eggs 20 | downloads 21 | Documentation/* 22 | .tox/ 23 | nosetests.xml 24 | kombu/tests/cover 25 | kombu/tests/coverage.xml 26 | .coverage 27 | dump.rdb 28 | .idea/ 29 | .vscode/ 30 | .cache/ 31 | .pytest_cache/ 32 | htmlcov/ 33 | test.db 34 | coverage.xml 35 | venv/ 36 | env 37 | .eggs 38 | .python-version 39 | .coverage.* 40 | control/ 41 | .env 42 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/asottile/pyupgrade 3 | rev: v3.19.1 4 | hooks: 5 | - id: pyupgrade 6 | args: ["--py38-plus"] 7 | 8 | - repo: https://github.com/PyCQA/autoflake 9 | rev: v2.3.1 10 | hooks: 11 | - id: autoflake 12 | args: ["--in-place", "--ignore-pass-after-docstring", "--imports"] 13 | 14 | - repo: https://github.com/PyCQA/flake8 15 | rev: 7.1.1 16 | hooks: 17 | - id: flake8 18 | 19 | - repo: https://github.com/asottile/yesqa 20 | rev: v1.5.0 21 | hooks: 22 | - id: yesqa 23 | 24 | - repo: https://github.com/codespell-project/codespell 25 | rev: v2.3.0 26 | hooks: 27 | - id: codespell # See pyproject.toml for args 28 | args: [--toml, pyproject.toml, --write-changes] 29 | additional_dependencies: 30 | - tomli 31 | 32 | - repo: https://github.com/pre-commit/pre-commit-hooks 33 | rev: v5.0.0 34 | hooks: 35 | - id: check-merge-conflict 36 | - id: check-toml 37 | - id: check-yaml 38 | - id: mixed-line-ending 39 | 40 | - repo: https://github.com/pycqa/isort 41 | rev: 5.13.2 42 | hooks: 43 | - id: isort 44 | 45 | - repo: https://github.com/pre-commit/mirrors-mypy 46 | rev: v1.14.1 47 | hooks: 48 | - id: mypy 49 | pass_filenames: false 50 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | # Required 5 | version: 2 6 | 7 | # Set the version of Python and other tools you might need 8 | build: 9 | os: ubuntu-20.04 10 | tools: 11 | python: "3.9" 12 | 13 | # Build documentation in the docs/ directory with Sphinx 14 | sphinx: 15 | configuration: docs/conf.py 16 | 17 | # If using Sphinx, optionally build your docs in additional formats such as PDF 18 | # formats: 19 | # - pdf 20 | 21 | # Optionally declare the Python requirements required to build your docs 22 | python: 23 | install: 24 | - method: pip 25 | path: . 26 | - requirements: requirements/docs.txt 27 | -------------------------------------------------------------------------------- /FAQ: -------------------------------------------------------------------------------- 1 | ============================ 2 | Frequently Asked Questions 3 | ============================ 4 | 5 | Questions 6 | ========= 7 | 8 | Q: Message.reject doesn't work? 9 | -------------------------------------- 10 | **Answer**: Earlier versions of RabbitMQ did not implement ``basic.reject``, 11 | so make sure your version is recent enough to support it. 12 | 13 | Q: Message.requeue doesn't work? 14 | -------------------------------------- 15 | 16 | **Answer**: See _`Message.reject doesn't work?` 17 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | You can install ``kombu`` either via the Python Package Index (PyPI) 5 | or from source. 6 | 7 | To install using ``pip``,:: 8 | 9 | $ pip install kombu 10 | 11 | 12 | To install using ``easy_install``,:: 13 | 14 | $ easy_install kombu 15 | 16 | 17 | If you have downloaded a source tarball you can install it 18 | by doing the following,:: 19 | 20 | $ python setup.py build 21 | # python setup.py install # as root 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2016 Ask Solem & contributors. All rights reserved. 2 | Copyright (c) 2012-2014 GoPivotal Inc & contributors. All rights reserved. 3 | Copyright (c) 2009-2012, Ask Solem & contributors. All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of Ask Solem nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 18 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Ask Solem OR CONTRIBUTORS 20 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include AUTHORS 2 | include Changelog 3 | include FAQ 4 | include INSTALL 5 | include LICENSE 6 | include MANIFEST.in 7 | include README.rst 8 | include README 9 | include THANKS 10 | include TODO 11 | include setup.cfg 12 | recursive-include extra * 13 | recursive-include docs * 14 | recursive-include kombu *.py 15 | recursive-include t *.py 16 | recursive-include requirements *.txt 17 | recursive-include funtests *.py setup.cfg 18 | recursive-include examples *.py 19 | 20 | recursive-exclude docs/_build * 21 | recursive-exclude * __pycache__ 22 | recursive-exclude * *.py[co] 23 | recursive-exclude * .*.sw* 24 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | | Version | Supported | 6 | | ------- | ------------------ | 7 | | 5.5.x | :white_check_mark: | 8 | | 5.4.x | :x: | 9 | | 5.3.x | :x: | 10 | | 5.2.x | :x: | 11 | | 5.1.x | :x: | 12 | | < 5.0 | :x: | 13 | 14 | ## Reporting a Vulnerability 15 | 16 | Please reach out to tomer.nosrati@gmail.com or auvipy@gmail.com for reporting security concerns via email. 17 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | ======== 2 | THANKS 3 | ======== 4 | 5 | From ``carrot`` THANKS file 6 | =========================== 7 | 8 | * Thanks to Barry Pederson for the py-amqplib library. 9 | * Thanks to Grégoire Cachet for bug reports. 10 | * Thanks to Martin Mahner for the Sphinx theme. 11 | * Thanks to jcater for bug reports. 12 | * Thanks to sebest for bug reports. 13 | * Thanks to greut for bug reports 14 | 15 | From ``django-kombu`` THANKS file 16 | ================================= 17 | 18 | * Thanks to Rajesh Dhawan and other authors of django-queue-service 19 | for the database model implementation. 20 | See http://code.google.com/p/django-queue-service/. 21 | 22 | From ``kombu-sqlalchemy`` THANKS file 23 | ===================================== 24 | 25 | * Thanks to Rajesh Dhawan and other authors of django-queue-service 26 | for the database model implementation. 27 | See http://code.google.com/p/django-queue-service/. 28 | 29 | * Thanks to haridsv for the draft SQLAlchemy port (which can still 30 | be found at http://github.com/haridsv/celery-alchemy-poc) 31 | 32 | 33 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Please see our Issue Tracker at GitHub: 2 | http://github.com/celery/kombu/issues 3 | -------------------------------------------------------------------------------- /conftest.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pytest 4 | 5 | 6 | def pytest_addoption(parser): 7 | parser.addoption( 8 | "-E", 9 | action="append", 10 | metavar="NAME", 11 | help="only run tests matching the environment NAME.", 12 | ) 13 | 14 | 15 | def pytest_configure(config): 16 | # register an additional marker 17 | config.addinivalue_line( 18 | "markers", 19 | "env(name): mark test to run only on named environment", 20 | ) 21 | config.addinivalue_line("markers", "replace_module_value") 22 | config.addinivalue_line("markers", "masked_modules") 23 | config.addinivalue_line("markers", "ensured_modules") 24 | config.addinivalue_line("markers", "sleepdeprived_patched_module") 25 | 26 | 27 | def pytest_runtest_setup(item): 28 | envnames = [mark.args[0] for mark in item.iter_markers(name='env')] 29 | if envnames: 30 | if ( 31 | item.config.getoption("-E") is None 32 | or len(set(item.config.getoption("-E")) & set(envnames)) == 0 33 | ): 34 | # We skip test if does not mentioned by -E param 35 | pytest.skip("test requires env in %r" % envnames) 36 | -------------------------------------------------------------------------------- /docs/_ext/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/docs/_ext/.keep -------------------------------------------------------------------------------- /docs/_static/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/docs/_static/.keep -------------------------------------------------------------------------------- /docs/_templates/sidebardonations.html: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /docs/changelog.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../Changelog.rst 2 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from sphinx_celery import conf 4 | 5 | globals().update(conf.build_config( 6 | 'kombu', __file__, 7 | project='Kombu', 8 | version_dev='5.4', 9 | version_stable='5.3', 10 | canonical_url='https://kombu.readthedocs.io/', 11 | webdomain='kombu.readthedocs.io', 12 | github_project='celery/kombu', 13 | author='Ask Solem & contributors', 14 | author_name='Ask Solem', 15 | copyright='2009-2019', 16 | publisher='Celery Project', 17 | html_logo='images/kombusmall.jpg', 18 | html_favicon='images/favicon.ico', 19 | html_prepend_sidebars=['sidebardonations.html'], 20 | extra_extensions=['sphinx.ext.napoleon'], 21 | apicheck_ignore_modules=[ 22 | 'kombu.entity', 23 | 'kombu.messaging', 24 | 'kombu.asynchronous.aws.ext', 25 | 'kombu.asynchronous.aws.sqs.ext', 26 | 'kombu.transport.qpid_patches', 27 | 'kombu.transport.librabbitmq', 28 | 'kombu.utils', 29 | 'kombu.transport.virtual.base', 30 | ], 31 | )) 32 | -------------------------------------------------------------------------------- /docs/faq.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../FAQ 2 | -------------------------------------------------------------------------------- /docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/docs/images/favicon.ico -------------------------------------------------------------------------------- /docs/images/kombu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/docs/images/kombu.jpg -------------------------------------------------------------------------------- /docs/images/kombusmall.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/docs/images/kombusmall.jpg -------------------------------------------------------------------------------- /docs/includes/installation.txt: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | You can install `Kombu` either via the Python Package Index (PyPI) 5 | or from source. 6 | 7 | To install using `pip`,: 8 | 9 | .. code-block:: console 10 | 11 | $ pip install kombu 12 | 13 | To install using `easy_install`,: 14 | 15 | .. code-block:: console 16 | 17 | $ easy_install kombu 18 | 19 | If you have downloaded a source tarball you can install it 20 | by doing the following,: 21 | 22 | .. code-block:: console 23 | 24 | $ python setup.py build 25 | # python setup.py install # as root 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/includes/resources.txt: -------------------------------------------------------------------------------- 1 | Getting Help 2 | ============ 3 | 4 | Mailing list 5 | ------------ 6 | 7 | Join the `carrot-users`_ mailing list. 8 | 9 | .. _`carrot-users`: http://groups.google.com/group/carrot-users/ 10 | 11 | Bug tracker 12 | =========== 13 | 14 | If you have any suggestions, bug reports or annoyances please report them 15 | to our issue tracker at http://github.com/celery/kombu/issues/ 16 | 17 | Contributing 18 | ============ 19 | 20 | Development of `Kombu` happens at Github: http://github.com/celery/kombu 21 | 22 | You are highly encouraged to participate in the development. If you don't 23 | like Github (for some reason) you're welcome to send regular patches. 24 | 25 | License 26 | ======= 27 | 28 | This software is licensed under the `New BSD License`. See the `LICENSE` 29 | file in the top distribution directory for the full license text. 30 | 31 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Kombu Documentation 2 | ================================== 3 | 4 | Contents: 5 | 6 | .. toctree:: 7 | :maxdepth: 2 8 | 9 | introduction 10 | userguide/index 11 | 12 | .. toctree:: 13 | :maxdepth: 1 14 | 15 | faq 16 | reference/index 17 | changelog 18 | 19 | 20 | Indices and tables 21 | ================== 22 | 23 | * :ref:`genindex` 24 | * :ref:`modindex` 25 | * :ref:`search` 26 | 27 | -------------------------------------------------------------------------------- /docs/introduction.rst: -------------------------------------------------------------------------------- 1 | ======================================== 2 | Getting Started 3 | ======================================== 4 | 5 | .. include:: includes/introduction.txt 6 | 7 | .. include:: includes/installation.txt 8 | 9 | .. include:: includes/resources.txt 10 | -------------------------------------------------------------------------------- /docs/reference/index.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | API Reference 3 | =========================== 4 | 5 | :Release: |version| 6 | :Date: |today| 7 | 8 | Kombu Core 9 | ========== 10 | 11 | .. toctree:: 12 | :maxdepth: 1 13 | 14 | kombu 15 | kombu.common 16 | kombu.matcher 17 | kombu.mixins 18 | kombu.simple 19 | kombu.clocks 20 | kombu.compat 21 | kombu.pidbox 22 | kombu.exceptions 23 | kombu.log 24 | kombu.connection 25 | kombu.message 26 | kombu.compression 27 | kombu.pools 28 | kombu.abstract 29 | kombu.resource 30 | kombu.serialization 31 | kombu.native_delayed_delivery 32 | 33 | Kombu Transports 34 | ================ 35 | 36 | .. toctree:: 37 | :maxdepth: 1 38 | 39 | kombu.transport 40 | kombu.transport.base 41 | kombu.transport.virtual 42 | kombu.transport.virtual.exchange 43 | kombu.transport.azurestoragequeues 44 | kombu.transport.azureservicebus 45 | kombu.transport.pyamqp 46 | kombu.transport.librabbitmq 47 | kombu.transport.qpid 48 | kombu.transport.memory 49 | kombu.transport.redis 50 | kombu.transport.mongodb 51 | kombu.transport.consul 52 | kombu.transport.etcd 53 | kombu.transport.zookeeper 54 | kombu.transport.filesystem 55 | kombu.transport.sqlalchemy 56 | kombu.transport.SQS 57 | kombu.transport.SLMQ 58 | kombu.transport.pyro 59 | 60 | 61 | Kombu Asynchronous 62 | ================== 63 | 64 | .. toctree:: 65 | :maxdepth: 1 66 | 67 | kombu.asynchronous 68 | kombu.asynchronous.hub 69 | kombu.asynchronous.semaphore 70 | kombu.asynchronous.timer 71 | kombu.asynchronous.debug 72 | kombu.asynchronous.http 73 | kombu.asynchronous.http.base 74 | kombu.asynchronous.http.urllib3_client 75 | kombu.asynchronous.aws 76 | kombu.asynchronous.aws.connection 77 | kombu.asynchronous.aws.sqs 78 | kombu.asynchronous.aws.sqs.connection 79 | kombu.asynchronous.aws.sqs.message 80 | kombu.asynchronous.aws.sqs.queue 81 | 82 | Kombu utils 83 | =========== 84 | 85 | .. toctree:: 86 | :maxdepth: 1 87 | 88 | kombu.utils.amq_manager 89 | kombu.utils.collections 90 | kombu.utils.compat 91 | kombu.utils.debug 92 | kombu.utils.div 93 | kombu.utils.encoding 94 | kombu.utils.eventio 95 | kombu.utils.functional 96 | kombu.utils.imports 97 | kombu.utils.json 98 | kombu.utils.limits 99 | kombu.utils.objects 100 | kombu.utils.scheduling 101 | kombu.utils.text 102 | kombu.utils.time 103 | kombu.utils.url 104 | kombu.utils.uuid 105 | -------------------------------------------------------------------------------- /docs/reference/kombu.abstract.rst: -------------------------------------------------------------------------------- 1 | ======================================= 2 | Abstract Classes - ``kombu.abstract`` 3 | ======================================= 4 | 5 | .. currentmodule:: kombu.abstract 6 | 7 | .. automodule:: kombu.abstract 8 | 9 | .. contents:: 10 | :local: 11 | 12 | .. autoclass:: MaybeChannelBound 13 | :members: 14 | :undoc-members: 15 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.aws.connection.rst: -------------------------------------------------------------------------------- 1 | ============================================================== 2 | Amazon AWS Connection - ``kombu.asynchronous.aws.connection`` 3 | ============================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.aws.connection 8 | 9 | .. automodule:: kombu.asynchronous.aws.connection 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.aws.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Async Amazon AWS Client - ``kombu.asynchronous.aws`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.aws 8 | 9 | .. automodule:: kombu.asynchronous.aws 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.aws.sqs.connection.rst: -------------------------------------------------------------------------------- 1 | =========================================================== 2 | SQS Connection - ``kombu.asynchronous.aws.sqs.connection`` 3 | =========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.aws.sqs.connection 8 | 9 | .. automodule:: kombu.asynchronous.aws.sqs.connection 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.aws.sqs.message.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | SQS Messages - ``kombu.asynchronous.aws.sqs.message`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.aws.sqs.message 8 | 9 | .. automodule:: kombu.asynchronous.aws.sqs.message 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.aws.sqs.queue.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | SQS Queues - ``kombu.asynchronous.aws.sqs.queue`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.aws.sqs.queue 8 | 9 | .. automodule:: kombu.asynchronous.aws.sqs.queue 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.aws.sqs.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Async Amazon SQS Client - ``kombu.asynchronous.aws.sqs`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.aws.sqs 8 | 9 | .. automodule:: kombu.asynchronous.aws.sqs 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.debug.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Event Loop Debugging Utils - ``kombu.asynchronous.debug`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.debug 8 | 9 | .. automodule:: kombu.asynchronous.debug 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.http.base.rst: -------------------------------------------------------------------------------- 1 | =============================================================== 2 | Async HTTP Client Interface - ``kombu.asynchronous.http.base`` 3 | =============================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.http.base 8 | 9 | .. automodule:: kombu.asynchronous.http.base 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.http.curl.rst: -------------------------------------------------------------------------------- 1 | ============================================================ 2 | Async pyCurl HTTP Client - ``kombu.asynchronous.http.curl`` 3 | ============================================================ 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.http.curl 8 | 9 | .. automodule:: kombu.asynchronous.http.curl 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.http.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Async HTTP Client - ``kombu.asynchronous.http`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.http 8 | 9 | .. automodule:: kombu.asynchronous.http 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.http.urllib3_client.rst: -------------------------------------------------------------------------------- 1 | ============================================================ 2 | Urllib3 HTTP Client Pool - ``kombu.asynchronous.http.urllib3_client`` 3 | ============================================================ 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.http.urllib3_client 8 | 9 | .. automodule:: kombu.asynchronous.http.urllib3_client 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.hub.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Event Loop Implementation - ``kombu.asynchronous.hub`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.hub 8 | 9 | .. automodule:: kombu.asynchronous.hub 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Event Loop - ``kombu.asynchronous`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous 8 | 9 | .. automodule:: kombu.asynchronous 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.semaphore.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Semaphores - ``kombu.asynchronous.semaphore`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.semaphore 8 | 9 | .. automodule:: kombu.asynchronous.semaphore 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.asynchronous.timer.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Timer - ``kombu.asynchronous.timer`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.asynchronous.timer 8 | 9 | .. automodule:: kombu.asynchronous.timer 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.clocks.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Logical Clocks and Synchronization - ``kombu.clocks`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.clocks 8 | 9 | .. automodule:: kombu.clocks 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.common.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Common Utilities - ``kombu.common`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.common 8 | 9 | .. automodule:: kombu.common 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.compat.rst: -------------------------------------------------------------------------------- 1 | ========================================== 2 | Carrot Compatibility - ``kombu.compat`` 3 | ========================================== 4 | 5 | .. currentmodule:: kombu.compat 6 | 7 | .. automodule:: kombu.compat 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Publisher 13 | --------- 14 | 15 | Replace with :class:`kombu.Producer`. 16 | 17 | .. autoclass:: Publisher 18 | :members: 19 | :undoc-members: 20 | :inherited-members: 21 | 22 | Consumer 23 | -------- 24 | 25 | Replace with :class:`kombu.Consumer`. 26 | 27 | .. autoclass:: Consumer 28 | :members: 29 | :undoc-members: 30 | :inherited-members: 31 | 32 | ConsumerSet 33 | ----------- 34 | 35 | Replace with :class:`kombu.Consumer`. 36 | 37 | .. autoclass:: ConsumerSet 38 | :members: 39 | :undoc-members: 40 | :inherited-members: 41 | -------------------------------------------------------------------------------- /docs/reference/kombu.compression.rst: -------------------------------------------------------------------------------- 1 | ============================================= 2 | Message Compression - ``kombu.compression`` 3 | ============================================= 4 | 5 | .. currentmodule:: kombu.compression 6 | 7 | .. automodule:: kombu.compression 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Encoding/decoding 13 | ----------------- 14 | 15 | .. autofunction:: compress 16 | .. autofunction:: decompress 17 | 18 | Registry 19 | -------- 20 | 21 | .. autofunction:: encoders 22 | .. autofunction:: get_encoder 23 | .. autofunction:: get_decoder 24 | .. autofunction:: register 25 | -------------------------------------------------------------------------------- /docs/reference/kombu.connection.rst: -------------------------------------------------------------------------------- 1 | ======================================= 2 | Connection - ``kombu.connection`` 3 | ======================================= 4 | 5 | .. currentmodule:: kombu.connection 6 | 7 | .. automodule:: kombu.connection 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Connection 13 | ---------- 14 | 15 | .. autoclass:: Connection 16 | :members: 17 | :undoc-members: 18 | 19 | Pools 20 | ----- 21 | 22 | .. seealso:: 23 | 24 | The shortcut methods :meth:`Connection.Pool` and 25 | :meth:`Connection.ChannelPool` is the recommended way 26 | to instantiate these classes. 27 | 28 | .. autoclass:: ConnectionPool 29 | 30 | .. autoattribute:: LimitExceeded 31 | 32 | .. automethod:: acquire 33 | .. automethod:: release 34 | .. automethod:: force_close_all 35 | 36 | .. autoclass:: ChannelPool 37 | 38 | .. autoattribute:: LimitExceeded 39 | 40 | .. automethod:: acquire 41 | .. automethod:: release 42 | .. automethod:: force_close_all 43 | -------------------------------------------------------------------------------- /docs/reference/kombu.exceptions.rst: -------------------------------------------------------------------------------- 1 | ===================================== 2 | Exceptions - ``kombu.exceptions`` 3 | ===================================== 4 | 5 | .. currentmodule:: kombu.exceptions 6 | 7 | .. automodule:: kombu.exceptions 8 | 9 | .. contents:: 10 | :local: 11 | 12 | .. autoexception:: NotBoundError 13 | .. autoexception:: MessageStateError 14 | .. autoexception:: TimeoutError 15 | .. autoexception:: LimitExceeded 16 | .. autoexception:: ConnectionLimitExceeded 17 | .. autoexception:: ChannelLimitExceeded 18 | 19 | -------------------------------------------------------------------------------- /docs/reference/kombu.log.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Logging - ``kombu.log`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.log 8 | 9 | .. automodule:: kombu.log 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.matcher.rst: -------------------------------------------------------------------------------- 1 | ============================================== 2 | Pattern matching registry - ``kombu.matcher`` 3 | ============================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.matcher 8 | 9 | .. automodule:: kombu.matcher 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.message.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Message Objects - ``kombu.message`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.message 8 | 9 | .. automodule:: kombu.message 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.mixins.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Mixin Classes - ``kombu.mixins`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.mixins 8 | 9 | .. automodule:: kombu.mixins 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.pidbox.rst: -------------------------------------------------------------------------------- 1 | ========================================= 2 | Pidbox - ``kombu.pidbox`` 3 | ========================================= 4 | 5 | 6 | .. currentmodule:: kombu.pidbox 7 | 8 | .. automodule:: kombu.pidbox 9 | 10 | .. contents:: 11 | :local: 12 | 13 | Introduction 14 | ------------ 15 | 16 | Creating the applications Mailbox 17 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 | 19 | .. code-block:: python 20 | 21 | >>> mailbox = pidbox.Mailbox('celerybeat', type='direct') 22 | 23 | >>> @mailbox.handler 24 | >>> def reload_schedule(state, **kwargs): 25 | ... state['beat'].reload_schedule() 26 | 27 | >>> @mailbox.handler 28 | >>> def connection_info(state, **kwargs): 29 | ... return {'connection': state['connection'].info()} 30 | 31 | Example Node 32 | ~~~~~~~~~~~~ 33 | 34 | .. code-block:: python 35 | 36 | >>> connection = kombu.Connection() 37 | >>> state = {'beat': beat, 38 | 'connection': connection} 39 | >>> consumer = mailbox(connection).Node(hostname).listen() 40 | >>> try: 41 | ... while True: 42 | ... connection.drain_events(timeout=1) 43 | ... finally: 44 | ... consumer.cancel() 45 | 46 | Example Client 47 | ~~~~~~~~~~~~~~ 48 | 49 | .. code-block:: python 50 | 51 | >>> mailbox.cast('reload_schedule') # cast is async. 52 | >>> info = celerybeat.call('connection_info', timeout=1) 53 | 54 | Mailbox 55 | ------- 56 | 57 | .. autoclass:: Mailbox 58 | 59 | .. autoattribute:: namespace 60 | .. autoattribute:: connection 61 | .. autoattribute:: type 62 | .. autoattribute:: exchange 63 | .. autoattribute:: reply_exchange 64 | 65 | .. automethod:: Node 66 | .. automethod:: call 67 | .. automethod:: cast 68 | .. automethod:: abcast 69 | .. automethod:: multi_call 70 | .. automethod:: get_reply_queue 71 | .. automethod:: get_queue 72 | 73 | Node 74 | ---- 75 | 76 | .. autoclass:: Node 77 | 78 | .. autoattribute:: hostname 79 | .. autoattribute:: mailbox 80 | .. autoattribute:: handlers 81 | .. autoattribute:: state 82 | .. autoattribute:: channel 83 | 84 | .. automethod:: Consumer 85 | .. automethod:: handler 86 | .. automethod:: listen 87 | .. automethod:: dispatch 88 | .. automethod:: dispatch_from_message 89 | .. automethod:: handle_call 90 | .. automethod:: handle_cast 91 | .. automethod:: handle 92 | .. automethod:: handle_message 93 | .. automethod:: reply 94 | 95 | -------------------------------------------------------------------------------- /docs/reference/kombu.pools.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Connection/Producer Pools - ``kombu.pools`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.pools 8 | 9 | .. automodule:: kombu.pools 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.resource.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Resource Management - ``kombu.resource`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.resource 8 | 9 | .. automodule:: kombu.resource 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.serialization.rst: -------------------------------------------------------------------------------- 1 | ================================================ 2 | Message Serialization - ``kombu.serialization`` 3 | ================================================ 4 | 5 | .. currentmodule:: kombu.serialization 6 | 7 | .. automodule:: kombu.serialization 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Overview 13 | -------- 14 | 15 | Centralized support for encoding/decoding of data structures. 16 | Contains json, pickle, msgpack, and yaml serializers. 17 | 18 | Optionally installs support for YAML if the `PyYAML`_ package 19 | is installed. 20 | 21 | Optionally installs support for `msgpack`_ if the `msgpack-python`_ 22 | package is installed. 23 | 24 | 25 | Exceptions 26 | ---------- 27 | 28 | .. autoexception:: SerializerNotInstalled 29 | 30 | Serialization 31 | ------------- 32 | 33 | .. autofunction:: dumps 34 | 35 | .. autofunction:: loads 36 | 37 | .. autofunction:: raw_encode 38 | 39 | Registry 40 | -------- 41 | 42 | .. autofunction:: register 43 | .. autofunction:: unregister 44 | 45 | .. autodata:: registry 46 | 47 | .. _`Python 2.7+`: https://docs.python.org/library/json.html 48 | .. _`PyYAML`: https://pyyaml.org/ 49 | .. _`msgpack`: https://msgpack.org/ 50 | .. _`msgpack-python`: https://pypi.org/project/msgpack-python/ 51 | -------------------------------------------------------------------------------- /docs/reference/kombu.simple.rst: -------------------------------------------------------------------------------- 1 | =============================================== 2 | Simple Messaging API - ``kombu.simple`` 3 | =============================================== 4 | 5 | .. currentmodule:: kombu.simple 6 | 7 | .. automodule:: kombu.simple 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Persistent 13 | ---------- 14 | 15 | .. autoclass:: SimpleQueue 16 | 17 | .. attribute:: channel 18 | 19 | Current channel 20 | 21 | .. attribute:: producer 22 | 23 | :class:`~kombu.Producer` used to publish messages. 24 | 25 | .. attribute:: consumer 26 | 27 | :class:`~kombu.Consumer` used to receive messages. 28 | 29 | .. attribute:: no_ack 30 | 31 | flag to enable/disable acknowledgments. 32 | 33 | .. attribute:: queue 34 | 35 | :class:`~kombu.Queue` to consume from (if consuming). 36 | 37 | .. attribute:: queue_opts 38 | 39 | Additional options for the queue declaration. 40 | 41 | .. attribute:: exchange_opts 42 | 43 | Additional options for the exchange declaration. 44 | 45 | .. automethod:: get 46 | .. automethod:: get_nowait 47 | .. automethod:: put 48 | .. automethod:: clear 49 | .. automethod:: __len__ 50 | .. automethod:: qsize 51 | .. automethod:: close 52 | 53 | Buffer 54 | ------ 55 | 56 | .. autoclass:: SimpleBuffer 57 | 58 | .. attribute:: channel 59 | 60 | Current channel 61 | 62 | .. attribute:: producer 63 | 64 | :class:`~kombu.Producer` used to publish messages. 65 | 66 | .. attribute:: consumer 67 | 68 | :class:`~kombu.Consumer` used to receive messages. 69 | 70 | .. attribute:: no_ack 71 | 72 | flag to enable/disable acknowledgments. 73 | 74 | .. attribute:: queue 75 | 76 | :class:`~kombu.Queue` to consume from (if consuming). 77 | 78 | .. attribute:: queue_opts 79 | 80 | Additional options for the queue declaration. 81 | 82 | .. attribute:: exchange_opts 83 | 84 | Additional options for the exchange declaration. 85 | 86 | .. automethod:: get 87 | .. automethod:: get_nowait 88 | .. automethod:: put 89 | .. automethod:: clear 90 | .. automethod:: __len__ 91 | .. automethod:: qsize 92 | .. automethod:: close 93 | 94 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.SLMQ.rst: -------------------------------------------------------------------------------- 1 | ============================================= 2 | SLMQ Transport - ``kombu.transport.SLMQ`` 3 | ============================================= 4 | 5 | 6 | .. currentmodule:: kombu.transport.SLMQ 7 | 8 | .. automodule:: kombu.transport.SLMQ 9 | 10 | .. contents:: 11 | :local: 12 | 13 | Transport 14 | --------- 15 | 16 | .. autoclass:: Transport 17 | :members: 18 | :undoc-members: 19 | 20 | Channel 21 | ------- 22 | 23 | .. autoclass:: Channel 24 | :members: 25 | :undoc-members: 26 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.SQS.rst: -------------------------------------------------------------------------------- 1 | ================================================ 2 | Amazon SQS Transport - ``kombu.transport.SQS`` 3 | ================================================ 4 | 5 | .. currentmodule:: kombu.transport.SQS 6 | 7 | .. automodule:: kombu.transport.SQS 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | 26 | Back-off policy 27 | ------------------------ 28 | Back-off policy is using SQS visibility timeout mechanism altering the time difference between task retries. 29 | The mechanism changes message specific ``visibility timeout`` from queue ``Default visibility timeout`` to policy configured timeout. 30 | The number of retries is managed by SQS (specifically by the ``ApproximateReceiveCount`` message attribute) and no further action is required by the user. 31 | 32 | Configuring the queues and backoff policy:: 33 | 34 | broker_transport_options = { 35 | 'predefined_queues': { 36 | 'my-q': { 37 | 'url': 'https://ap-southeast-2.queue.amazonaws.com/123456/my-q', 38 | 'access_key_id': 'xxx', 39 | 'secret_access_key': 'xxx', 40 | 'backoff_policy': {1: 10, 2: 20, 3: 40, 4: 80, 5: 320, 6: 640}, 41 | 'backoff_tasks': ['svc.tasks.tasks.task1'] 42 | } 43 | } 44 | } 45 | 46 | 47 | ``backoff_policy`` dictionary where key is number of retries, and value is delay seconds between retries (i.e 48 | SQS visibility timeout) 49 | ``backoff_tasks`` list of task names to apply the above policy 50 | 51 | The above policy: 52 | 53 | +-----------------------------------------+--------------------------------------------+ 54 | | **Attempt** | **Delay** | 55 | +-----------------------------------------+--------------------------------------------+ 56 | | ``2nd attempt`` | 20 seconds | 57 | +-----------------------------------------+--------------------------------------------+ 58 | | ``3rd attempt`` | 40 seconds | 59 | +-----------------------------------------+--------------------------------------------+ 60 | | ``4th attempt`` | 80 seconds | 61 | +-----------------------------------------+--------------------------------------------+ 62 | | ``5th attempt`` | 320 seconds | 63 | +-----------------------------------------+--------------------------------------------+ 64 | | ``6th attempt`` | 640 seconds | 65 | +-----------------------------------------+--------------------------------------------+ 66 | 67 | 68 | Message Attributes 69 | ------------------------ 70 | 71 | SQS supports sending message attributes along with the message body. 72 | To use this feature, you can pass a 'message_attributes' as keyword argument 73 | to `basic_publish` method. -------------------------------------------------------------------------------- /docs/reference/kombu.transport.azureservicebus.rst: -------------------------------------------------------------------------------- 1 | ================================================================== 2 | Azure Service Bus Transport - ``kombu.transport.azureservicebus`` 3 | ================================================================== 4 | 5 | .. currentmodule:: kombu.transport.azureservicebus 6 | 7 | .. automodule:: kombu.transport.azureservicebus 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.azurestoragequeues.rst: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | Azure Storage Queues Transport - ``kombu.transport.azurestoragequeues`` 3 | ======================================================================== 4 | 5 | .. currentmodule:: kombu.transport.azurestoragequeues 6 | 7 | .. automodule:: kombu.transport.azurestoragequeues 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.base.rst: -------------------------------------------------------------------------------- 1 | ================================================== 2 | Transport Base Class - ``kombu.transport.base`` 3 | ================================================== 4 | 5 | .. currentmodule:: kombu.transport.base 6 | 7 | .. automodule:: kombu.transport.base 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Message 13 | ------- 14 | 15 | .. autoclass:: Message 16 | 17 | .. autoattribute:: payload 18 | .. autoattribute:: channel 19 | .. autoattribute:: delivery_tag 20 | .. autoattribute:: content_type 21 | .. autoattribute:: content_encoding 22 | .. autoattribute:: delivery_info 23 | .. autoattribute:: headers 24 | .. autoattribute:: properties 25 | .. autoattribute:: body 26 | .. autoattribute:: acknowledged 27 | 28 | .. automethod:: ack 29 | .. automethod:: reject 30 | .. automethod:: requeue 31 | .. automethod:: decode 32 | 33 | Transport 34 | --------- 35 | 36 | .. autoclass:: Transport 37 | 38 | .. autoattribute:: client 39 | .. autoattribute:: default_port 40 | 41 | .. attribute:: recoverable_connection_errors 42 | 43 | Optional list of connection related exceptions that can be 44 | recovered from, but where the connection must be closed 45 | and re-established first. 46 | 47 | If not defined then all :attr:`connection_errors` and 48 | :class:`channel_errors` will be regarded as recoverable, 49 | but needing to close the connection first. 50 | 51 | .. attribute:: recoverable_channel_errors 52 | 53 | Optional list of channel related exceptions that can be 54 | automatically recovered from without re-establishing the 55 | connection. 56 | 57 | .. autoattribute:: connection_errors 58 | .. autoattribute:: channel_errors 59 | 60 | .. automethod:: establish_connection 61 | .. automethod:: close_connection 62 | .. automethod:: create_channel 63 | .. automethod:: close_channel 64 | .. automethod:: drain_events 65 | 66 | 67 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.confluentkafka.rst: -------------------------------------------------------------------------------- 1 | ========================================================= 2 | confluent-kafka Transport - ``kombu.transport.confluentkafka`` 3 | ========================================================= 4 | 5 | .. currentmodule:: kombu.transport.confluentkafka 6 | 7 | .. automodule:: kombu.transport.confluentkafka 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | 26 | Message 27 | ------- 28 | 29 | .. autoclass:: Message 30 | :members: 31 | :undoc-members: 32 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.consul.rst: -------------------------------------------------------------------------------- 1 | ================================================ 2 | Consul Transport - ``kombu.transport.consul`` 3 | ================================================ 4 | 5 | .. currentmodule:: kombu.transport.consul 6 | 7 | .. automodule:: kombu.transport.consul 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.etcd.rst: -------------------------------------------------------------------------------- 1 | ================================================ 2 | Etcd Transport - ``kombu.transport.etcd`` 3 | ================================================ 4 | 5 | .. currentmodule:: kombu.transport.etcd 6 | 7 | .. automodule:: kombu.transport.etcd 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.filesystem.rst: -------------------------------------------------------------------------------- 1 | ======================================================== 2 | File-system Transport - ``kombu.transport.filesystem`` 3 | ======================================================== 4 | 5 | .. currentmodule:: kombu.transport.filesystem 6 | 7 | .. automodule:: kombu.transport.filesystem 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | 26 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.gcpubsub.rst: -------------------------------------------------------------------------------- 1 | ============================================================== 2 | Google Cloud Pub/Sub Transport - ``kombu.transport.gcpubsub`` 3 | ============================================================== 4 | 5 | .. currentmodule:: kombu.transport.gcpubsub 6 | 7 | .. automodule:: kombu.transport.gcpubsub 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.librabbitmq.rst: -------------------------------------------------------------------------------- 1 | =============================================================== 2 | librabbitmq AMQP transport - ``kombu.transport.librabbitmq`` 3 | =============================================================== 4 | 5 | .. currentmodule:: kombu.transport.librabbitmq 6 | 7 | .. automodule:: kombu.transport.librabbitmq 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Connection 20 | ---------- 21 | 22 | .. autoclass:: Connection 23 | :members: 24 | :undoc-members: 25 | :inherited-members: 26 | 27 | Channel 28 | ------- 29 | 30 | .. autoclass:: Channel 31 | :members: 32 | :undoc-members: 33 | 34 | Message 35 | ------- 36 | 37 | .. autoclass:: Message 38 | :members: 39 | :undoc-members: 40 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.memory.rst: -------------------------------------------------------------------------------- 1 | ================================================== 2 | In-memory Transport - ``kombu.transport.memory`` 3 | ================================================== 4 | 5 | .. currentmodule:: kombu.transport.memory 6 | 7 | .. automodule:: kombu.transport.memory 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.mongodb.rst: -------------------------------------------------------------------------------- 1 | ================================================= 2 | MongoDB Transport - ``kombu.transport.mongodb`` 3 | ================================================= 4 | 5 | .. currentmodule:: kombu.transport.mongodb 6 | 7 | .. automodule:: kombu.transport.mongodb 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.native_delayed_delivery.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Native Delayed Delivery - ``native_delayed_delivery`` 3 | ========================================================== 4 | 5 | .. versionadded:: 5.5 6 | 7 | .. contents:: 8 | :local: 9 | .. currentmodule:: kombu.transport.native_delayed_delivery 10 | 11 | .. automodule:: kombu.transport.native_delayed_delivery 12 | :members: 13 | :undoc-members: 14 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.pyamqp.rst: -------------------------------------------------------------------------------- 1 | ========================================================= 2 | Pure-python AMQP Transport - ``kombu.transport.pyamqp`` 3 | ========================================================= 4 | 5 | .. currentmodule:: kombu.transport.pyamqp 6 | 7 | .. automodule:: kombu.transport.pyamqp 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Connection 20 | ---------- 21 | 22 | .. autoclass:: Connection 23 | :members: 24 | :undoc-members: 25 | :inherited-members: 26 | 27 | Channel 28 | ------- 29 | 30 | .. autoclass:: Channel 31 | :members: 32 | :undoc-members: 33 | 34 | Message 35 | ------- 36 | 37 | .. autoclass:: Message 38 | :members: 39 | :undoc-members: 40 | 41 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.pyro.rst: -------------------------------------------------------------------------------- 1 | ================================================ 2 | Pyro Transport - ``kombu.transport.pyro`` 3 | ================================================ 4 | 5 | .. currentmodule:: kombu.transport.pyro 6 | 7 | .. automodule:: kombu.transport.pyro 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | 26 | 27 | KombuBroker 28 | ----------- 29 | 30 | .. autoclass:: KombuBroker 31 | :members: 32 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.qpid.rst: -------------------------------------------------------------------------------- 1 | =================================================== 2 | Apache QPid Transport - ``kombu.transport.qpid`` 3 | =================================================== 4 | 5 | .. currentmodule:: kombu.transport.qpid 6 | 7 | .. automodule:: kombu.transport.qpid 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Connection 20 | ---------- 21 | 22 | .. autoclass:: Connection 23 | :members: 24 | :undoc-members: 25 | 26 | Channel 27 | ------- 28 | 29 | .. autoclass:: Channel 30 | :members: 31 | :undoc-members: 32 | 33 | Message 34 | ------- 35 | 36 | .. autoclass:: Message 37 | :members: 38 | :undoc-members: 39 | 40 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.redis.rst: -------------------------------------------------------------------------------- 1 | ================================================= 2 | Redis Transport - ``kombu.transport.redis`` 3 | ================================================= 4 | 5 | .. currentmodule:: kombu.transport.redis 6 | 7 | .. automodule:: kombu.transport.redis 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | 26 | SentinelChannel 27 | --------------- 28 | 29 | .. autoclass:: SentinelChannel 30 | :members: 31 | :undoc-members: 32 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.rst: -------------------------------------------------------------------------------- 1 | =========================================== 2 | Built-in Transports - ``kombu.transport`` 3 | =========================================== 4 | 5 | .. currentmodule:: kombu.transport 6 | 7 | .. automodule:: kombu.transport 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Data 13 | ---- 14 | 15 | .. data:: DEFAULT_TRANSPORT 16 | 17 | Default transport used when no transport specified. 18 | 19 | .. data:: TRANSPORT_ALIASES 20 | 21 | Mapping of transport aliases/class names. 22 | 23 | Functions 24 | --------- 25 | 26 | .. autofunction:: get_transport_cls 27 | .. autofunction:: resolve_transport 28 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.sqlalchemy.rst: -------------------------------------------------------------------------------- 1 | ============================================================= 2 | SQLAlchemy Transport Model - ``kombu.transport.sqlalchemy`` 3 | ============================================================= 4 | 5 | 6 | .. currentmodule:: kombu.transport.sqlalchemy 7 | 8 | .. automodule:: kombu.transport.sqlalchemy 9 | 10 | .. contents:: 11 | :local: 12 | 13 | Transport 14 | --------- 15 | 16 | .. autoclass:: Transport 17 | :members: 18 | :undoc-members: 19 | 20 | Channel 21 | ------- 22 | 23 | .. autoclass:: Channel 24 | :members: 25 | :undoc-members: 26 | 27 | SQLAlchemy Transport Model - ``kombu.transport.sqlalchemy.models`` 28 | ================================================================== 29 | 30 | 31 | .. currentmodule:: kombu.transport.sqlalchemy.models 32 | 33 | .. automodule:: kombu.transport.sqlalchemy.models 34 | 35 | .. contents:: 36 | :local: 37 | 38 | Models 39 | ------ 40 | 41 | .. autoclass:: Queue 42 | 43 | .. autoattribute:: Queue.id 44 | 45 | .. autoattribute:: Queue.name 46 | 47 | .. autoclass:: Message 48 | 49 | .. autoattribute:: Message.id 50 | 51 | .. autoattribute:: Message.visible 52 | 53 | .. autoattribute:: Message.sent_at 54 | 55 | .. autoattribute:: Message.payload 56 | 57 | .. autoattribute:: Message.version 58 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.virtual.exchange.rst: -------------------------------------------------------------------------------- 1 | ============================================================================= 2 | Virtual AMQ Exchange Implementation - ``kombu.transport.virtual.exchange`` 3 | ============================================================================= 4 | 5 | .. currentmodule:: kombu.transport.virtual.exchange 6 | 7 | .. automodule:: kombu.transport.virtual.exchange 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Direct 13 | ------ 14 | 15 | .. autoclass:: DirectExchange 16 | :members: 17 | :undoc-members: 18 | 19 | Topic 20 | ----- 21 | 22 | .. autoclass:: TopicExchange 23 | :members: 24 | :undoc-members: 25 | 26 | Fanout 27 | ------ 28 | 29 | .. autoclass:: FanoutExchange 30 | :members: 31 | :undoc-members: 32 | 33 | Interface 34 | --------- 35 | 36 | .. autoclass:: ExchangeType 37 | :members: 38 | :undoc-members: 39 | 40 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.virtual.rst: -------------------------------------------------------------------------------- 1 | ============================================================ 2 | Virtual Transport Base Class - ``kombu.transport.virtual`` 3 | ============================================================ 4 | 5 | .. currentmodule:: kombu.transport.virtual 6 | 7 | .. automodule:: kombu.transport.virtual 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transports 13 | ---------- 14 | 15 | .. autoclass:: Transport 16 | 17 | .. autoattribute:: Channel 18 | 19 | .. autoattribute:: Cycle 20 | 21 | .. autoattribute:: polling_interval 22 | 23 | .. autoattribute:: default_port 24 | 25 | .. autoattribute:: state 26 | 27 | .. autoattribute:: cycle 28 | 29 | .. automethod:: establish_connection 30 | 31 | .. automethod:: close_connection 32 | 33 | .. automethod:: create_channel 34 | 35 | .. automethod:: close_channel 36 | 37 | .. automethod:: drain_events 38 | 39 | Channel 40 | ------- 41 | 42 | .. autoclass:: AbstractChannel 43 | :members: 44 | 45 | .. autoclass:: Channel 46 | 47 | .. autoattribute:: Message 48 | 49 | .. autoattribute:: state 50 | 51 | .. autoattribute:: qos 52 | 53 | .. autoattribute:: do_restore 54 | 55 | .. autoattribute:: exchange_types 56 | 57 | .. automethod:: exchange_declare 58 | 59 | .. automethod:: exchange_delete 60 | 61 | .. automethod:: queue_declare 62 | 63 | .. automethod:: queue_delete 64 | 65 | .. automethod:: queue_bind 66 | 67 | .. automethod:: queue_purge 68 | 69 | .. automethod:: basic_publish 70 | 71 | .. automethod:: basic_consume 72 | 73 | .. automethod:: basic_cancel 74 | 75 | .. automethod:: basic_get 76 | 77 | .. automethod:: basic_ack 78 | 79 | .. automethod:: basic_recover 80 | 81 | .. automethod:: basic_reject 82 | 83 | .. automethod:: basic_qos 84 | 85 | .. automethod:: get_table 86 | 87 | .. automethod:: typeof 88 | 89 | .. automethod:: drain_events 90 | 91 | .. automethod:: prepare_message 92 | 93 | .. automethod:: message_to_python 94 | 95 | .. automethod:: flow 96 | 97 | .. automethod:: close 98 | 99 | Message 100 | ------- 101 | 102 | .. autoclass:: Message 103 | :members: 104 | :undoc-members: 105 | :inherited-members: 106 | 107 | Quality Of Service 108 | ------------------ 109 | 110 | .. autoclass:: QoS 111 | :members: 112 | :undoc-members: 113 | :inherited-members: 114 | 115 | In-memory State 116 | --------------- 117 | 118 | .. autoclass:: BrokerState 119 | :members: 120 | :undoc-members: 121 | :inherited-members: 122 | -------------------------------------------------------------------------------- /docs/reference/kombu.transport.zookeeper.rst: -------------------------------------------------------------------------------- 1 | ====================================================== 2 | Zookeeper Transport - ``kombu.transport.zookeeper`` 3 | ====================================================== 4 | 5 | .. currentmodule:: kombu.transport.zookeeper 6 | 7 | .. automodule:: kombu.transport.zookeeper 8 | 9 | .. contents:: 10 | :local: 11 | 12 | Transport 13 | --------- 14 | 15 | .. autoclass:: Transport 16 | :members: 17 | :undoc-members: 18 | 19 | Channel 20 | ------- 21 | 22 | .. autoclass:: Channel 23 | :members: 24 | :undoc-members: 25 | 26 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.amq_manager.rst: -------------------------------------------------------------------------------- 1 | ======================================================== 2 | Generic RabbitMQ manager - ``kombu.utils.amq_manager`` 3 | ======================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.amq_manager 8 | 9 | .. automodule:: kombu.utils.amq_manager 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.collections.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Custom Collections - ``kombu.utils.collections`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.collections 8 | 9 | .. automodule:: kombu.utils.collections 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.compat.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Python Compatibility - ``kombu.utils.compat`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.compat 8 | 9 | .. automodule:: kombu.utils.compat 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.debug.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Debugging Utilities - ``kombu.utils.debug`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.debug 8 | 9 | .. automodule:: kombu.utils.debug 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.div.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Div Utilities - ``kombu.utils.div`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.div 8 | 9 | .. automodule:: kombu.utils.div 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.encoding.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | String Encoding Utilities - ``kombu.utils.encoding`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.encoding 8 | 9 | .. automodule:: kombu.utils.encoding 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.eventio.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Async I/O Selectors - ``kombu.utils.eventio`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.eventio 8 | 9 | .. automodule:: kombu.utils.eventio 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.functional.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Functional-style Utilities - ``kombu.utils.functional`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.functional 8 | 9 | .. automodule:: kombu.utils.functional 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.imports.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Module Importing Utilities - ``kombu.utils.imports`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.imports 8 | 9 | .. automodule:: kombu.utils.imports 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.json.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | JSON Utilities - ``kombu.utils.json`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.json 8 | 9 | .. automodule:: kombu.utils.json 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.limits.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Rate limiting - ``kombu.utils.limits`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.limits 8 | 9 | .. automodule:: kombu.utils.limits 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.objects.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Object/Property Utilities - ``kombu.utils.objects`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.objects 8 | 9 | .. automodule:: kombu.utils.objects 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.scheduling.rst: -------------------------------------------------------------------------------- 1 | ================================================= 2 | Consumer Scheduling - ``kombu.utils.scheduling`` 3 | ================================================= 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.scheduling 8 | 9 | .. automodule:: kombu.utils.scheduling 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.text.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Text utilitites - ``kombu.utils.text`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.text 8 | 9 | .. automodule:: kombu.utils.text 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.time.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | Time Utilities - ``kombu.utils.time`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.time 8 | 9 | .. automodule:: kombu.utils.time 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.url.rst: -------------------------------------------------------------------------------- 1 | ============================================== 2 | URL Utilities - ``kombu.utils.url`` 3 | ============================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.url 8 | 9 | .. automodule:: kombu.utils.url 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/reference/kombu.utils.uuid.rst: -------------------------------------------------------------------------------- 1 | ========================================================== 2 | UUID Utilities - ``kombu.utils.uuid`` 3 | ========================================================== 4 | 5 | .. contents:: 6 | :local: 7 | .. currentmodule:: kombu.utils.uuid 8 | 9 | .. automodule:: kombu.utils.uuid 10 | :members: 11 | :undoc-members: 12 | -------------------------------------------------------------------------------- /docs/templates/readme.txt: -------------------------------------------------------------------------------- 1 | ======================================== 2 | kombu - Messaging library for Python 3 | ======================================== 4 | 5 | |build-status| |coverage| |license| |wheel| |pyversion| |pyimp| 6 | 7 | .. include:: ../includes/introduction.txt 8 | 9 | .. include:: ../includes/installation.txt 10 | 11 | .. include:: ../includes/resources.txt 12 | 13 | .. |build-status| image:: https://github.com/celery/kombu/actions/workflows/ci.yaml/badge.svg 14 | :alt: Build status 15 | :target: https://github.com/celery/kombu/actions/workflows/ci.yml 16 | 17 | .. |coverage| image:: https://codecov.io/github/celery/kombu/coverage.svg?branch=main 18 | :target: https://codecov.io/github/celery/kombu?branch=main 19 | 20 | .. |license| image:: https://img.shields.io/pypi/l/kombu.svg 21 | :alt: BSD License 22 | :target: https://opensource.org/licenses/BSD-3-Clause 23 | 24 | .. |wheel| image:: https://img.shields.io/pypi/wheel/kombu.svg 25 | :alt: Kombu can be installed via wheel 26 | :target: https://pypi.org/project/kombu/ 27 | 28 | .. |pyversion| image:: https://img.shields.io/pypi/pyversions/kombu.svg 29 | :alt: Supported Python versions. 30 | :target: https://pypi.org/project/kombu/ 31 | 32 | .. |pyimp| image:: https://img.shields.io/pypi/implementation/kombu.svg 33 | :alt: Support Python implementations. 34 | :target: https://pypi.org/project/kombu/ 35 | -- 36 | -------------------------------------------------------------------------------- /docs/userguide/examples.rst: -------------------------------------------------------------------------------- 1 | .. _examples: 2 | 3 | ======================== 4 | Examples 5 | ======================== 6 | 7 | .. _hello-world-example: 8 | 9 | Hello World Example 10 | =================== 11 | 12 | Below example uses 13 | :ref:`guide-simple` 14 | to send helloworld message through 15 | message broker (rabbitmq) and print received message 16 | 17 | 18 | :file:`hello_publisher.py`: 19 | 20 | .. literalinclude:: ../../examples/hello_publisher.py 21 | :language: python 22 | 23 | :file:`hello_consumer.py`: 24 | 25 | .. literalinclude:: ../../examples/hello_consumer.py 26 | :language: python 27 | 28 | 29 | .. _task-queue-example: 30 | 31 | Task Queue Example 32 | ================== 33 | 34 | Very simple task queue using pickle, with primitive support 35 | for priorities using different queues. 36 | 37 | 38 | :file:`queues.py`: 39 | 40 | .. literalinclude:: ../../examples/simple_task_queue/queues.py 41 | :language: python 42 | 43 | :file:`worker.py`: 44 | 45 | .. literalinclude:: ../../examples/simple_task_queue/worker.py 46 | :language: python 47 | 48 | :file:`tasks.py`: 49 | 50 | .. literalinclude:: ../../examples/simple_task_queue/tasks.py 51 | :language: python 52 | 53 | :file:`client.py`: 54 | 55 | .. literalinclude:: ../../examples/simple_task_queue/client.py 56 | 57 | .. _native-delayed-delivery-example: 58 | 59 | Native Delayed Delivery 60 | ======================= 61 | 62 | This example demonstrates how to declare native delayed delivery queues and exchanges and publish a message using 63 | the native delayed delivery mechanism. 64 | 65 | :file:`delayed_infra.py`: 66 | 67 | .. literalinclude:: ../../examples/delayed_infra.py 68 | :language: python 69 | -------------------------------------------------------------------------------- /docs/userguide/index.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | User Guide 3 | ============ 4 | 5 | :Release: |version| 6 | :Date: |today| 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | 11 | introduction 12 | connections 13 | producers 14 | consumers 15 | examples 16 | simple 17 | pools 18 | serialization 19 | failover 20 | -------------------------------------------------------------------------------- /docs/userguide/introduction.rst: -------------------------------------------------------------------------------- 1 | .. _guide-intro: 2 | 3 | ============== 4 | Introduction 5 | ============== 6 | 7 | .. _intro-messaging: 8 | 9 | What is messaging? 10 | ================== 11 | 12 | In times long ago people didn't have email. 13 | They had the postal service, which with great courage would deliver mail 14 | from hand to hand all over the globe. Soldiers deployed at wars far away could only 15 | communicate with their families through the postal service, and 16 | posting a letter would mean that the recipient wouldn't actually 17 | receive the letter until weeks or months, sometimes years later. 18 | 19 | It's hard to imagine this today when people are expected to be available 20 | for phone calls every minute of the day. 21 | 22 | So humans need to communicate with each other, this shouldn't 23 | be news to anyone, but why would applications? 24 | 25 | One example is banks. 26 | When you transfer money from one bank to another, your bank sends 27 | a message to a central clearinghouse. The clearinghouse 28 | then records and coordinates the transaction. Banks 29 | need to send and receive millions and millions of 30 | messages every day, and losing a single message would mean either losing 31 | your money (bad) or the banks money (very bad) 32 | 33 | Another example is the stock exchanges, which also have a need 34 | for very high message throughputs and have strict reliability 35 | requirements. 36 | 37 | Email is a great way for people to communicate. It is much faster 38 | than using the postal service, but still using email as a means for 39 | programs to communicate would be like the soldier above, waiting 40 | for signs of life from his girlfriend back home. 41 | 42 | .. _messaging-scenarios: 43 | 44 | Messaging Scenarios 45 | =================== 46 | 47 | * Request/Reply 48 | 49 | The request/reply pattern works like the postal service example. 50 | A message is addressed to a single recipient, with a return address 51 | printed on the back. The recipient may or may not reply to the 52 | message by sending it back to the original sender. 53 | 54 | Request-Reply is achieved using *direct* exchanges. 55 | 56 | * Broadcast 57 | 58 | In a broadcast scenario a message is sent to all parties. 59 | This could be none, one or many recipients. 60 | 61 | Broadcast is achieved using *fanout* exchanges. 62 | 63 | * Publish/Subscribe 64 | 65 | In a publish/subscribe scenario producers publish messages 66 | to topics, and consumers subscribe to the topics they are 67 | interested in. 68 | 69 | If no consumers subscribe to the topic, then the message 70 | will not be delivered to anyone. If several consumers 71 | subscribe to the topic, then the message will be delivered 72 | to all of them. 73 | 74 | Pub-sub is achieved using *topic* exchanges. 75 | 76 | .. _messaging-reliability: 77 | 78 | Reliability 79 | =========== 80 | 81 | For some applications reliability is very important. Losing a message is 82 | a critical situation that must never happen. For other applications 83 | losing a message is fine, it can maybe recover in other ways, 84 | or the message is resent anyway as periodic updates. 85 | 86 | AMQP defines two built-in delivery modes: 87 | 88 | * persistent 89 | 90 | Messages are written to disk and survives a broker restart. 91 | 92 | * transient 93 | 94 | Messages may or may not be written to disk, as the broker sees fit 95 | to optimize memory contents. The messages won't survive a broker 96 | restart. 97 | 98 | Transient messaging is by far the fastest way to send and receive messages, 99 | so having persistent messages comes with a price, but for some 100 | applications this is a necessary cost. 101 | -------------------------------------------------------------------------------- /examples/complete_receive.py: -------------------------------------------------------------------------------- 1 | """ 2 | Example of simple consumer that waits for a single message, acknowledges it 3 | and exits. 4 | 5 | """ 6 | 7 | from __future__ import annotations 8 | 9 | from pprint import pformat 10 | 11 | from kombu import Connection, Consumer, Exchange, Queue, eventloop 12 | 13 | #: By default messages sent to exchanges are persistent (delivery_mode=2), 14 | #: and queues and exchanges are durable. 15 | exchange = Exchange('kombu_demo', type='direct') 16 | queue = Queue('kombu_demo', exchange, routing_key='kombu_demo') 17 | 18 | 19 | def pretty(obj): 20 | return pformat(obj, indent=4) 21 | 22 | 23 | #: This is the callback applied when a message is received. 24 | def handle_message(body, message): 25 | print(f'Received message: {body!r}') 26 | print(f' properties:\n{pretty(message.properties)}') 27 | print(f' delivery_info:\n{pretty(message.delivery_info)}') 28 | message.ack() 29 | 30 | 31 | #: Create a connection and a channel. 32 | #: If hostname, userid, password and virtual_host is not specified 33 | #: the values below are the default, but listed here so it can 34 | #: be easily changed. 35 | with Connection('amqp://guest:guest@localhost:5672//') as connection: 36 | 37 | #: Create consumer using our callback and queue. 38 | #: Second argument can also be a list to consume from 39 | #: any number of queues. 40 | with Consumer(connection, queue, callbacks=[handle_message]): 41 | 42 | #: Each iteration waits for a single event. Note that this 43 | #: event may not be a message, or a message that is to be 44 | #: delivered to the consumers channel, but any event received 45 | #: on the connection. 46 | for _ in eventloop(connection): 47 | pass 48 | -------------------------------------------------------------------------------- /examples/complete_send.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Example producer that sends a single message and exits. 4 | 5 | You can use `complete_receive.py` to receive the message sent. 6 | 7 | """ 8 | 9 | from __future__ import annotations 10 | 11 | from kombu import Connection, Exchange, Producer, Queue 12 | 13 | #: By default messages sent to exchanges are persistent (delivery_mode=2), 14 | #: and queues and exchanges are durable. 15 | exchange = Exchange('kombu_demo', type='direct') 16 | queue = Queue('kombu_demo', exchange, routing_key='kombu_demo') 17 | 18 | 19 | with Connection('amqp://guest:guest@localhost:5672//') as connection: 20 | 21 | #: Producers are used to publish messages. 22 | #: a default exchange and routing key can also be specified 23 | #: as arguments the Producer, but we rather specify this explicitly 24 | #: at the publish call. 25 | producer = Producer(connection) 26 | 27 | #: Publish the message using the json serializer (which is the default), 28 | #: and zlib compression. The kombu consumer will automatically detect 29 | #: encoding, serialization and compression used and decode accordingly. 30 | producer.publish( 31 | {'hello': 'world'}, 32 | exchange=exchange, 33 | routing_key='kombu_demo', 34 | serializer='json', 35 | compression='zlib', 36 | ) 37 | -------------------------------------------------------------------------------- /examples/delayed_infra.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from kombu import Connection, Exchange, Queue 4 | from kombu.transport.native_delayed_delivery import ( 5 | bind_queue_to_native_delayed_delivery_exchange, calculate_routing_key, 6 | declare_native_delayed_delivery_exchanges_and_queues, level_name) 7 | 8 | with Connection('amqp://guest:guest@localhost:5672//') as connection: 9 | declare_native_delayed_delivery_exchanges_and_queues(connection, 'quorum') 10 | channel = connection.channel() 11 | 12 | destination_exchange = Exchange('destination_exchange', type='topic') 13 | queue = Queue("destination", exchange=destination_exchange, routing_key='destination_route') 14 | queue.declare(channel=connection.channel()) 15 | 16 | bind_queue_to_native_delayed_delivery_exchange(connection, queue) 17 | with connection.Producer(channel=channel) as producer: 18 | routing_key = calculate_routing_key(30, 'destination_route') 19 | producer.publish( 20 | "delayed msg", 21 | routing_key=routing_key, 22 | exchange=level_name(27) 23 | ) 24 | -------------------------------------------------------------------------------- /examples/experimental/async_consume.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from __future__ import annotations 4 | 5 | from kombu import Connection, Consumer, Exchange, Producer, Queue 6 | from kombu.asynchronous import Hub 7 | 8 | hub = Hub() 9 | exchange = Exchange('asynt') 10 | queue = Queue('asynt', exchange, 'asynt') 11 | 12 | 13 | def send_message(conn): 14 | producer = Producer(conn) 15 | producer.publish('hello world', exchange=exchange, routing_key='asynt') 16 | print('message sent') 17 | 18 | 19 | def on_message(message): 20 | print(f'received: {message.body!r}') 21 | message.ack() 22 | hub.stop() # <-- exit after one message 23 | 24 | 25 | if __name__ == '__main__': 26 | conn = Connection('amqp://') 27 | conn.register_with_event_loop(hub) 28 | 29 | with Consumer(conn, [queue], on_message=on_message): 30 | send_message(conn) 31 | hub.run_forever() 32 | -------------------------------------------------------------------------------- /examples/hello_consumer.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from kombu import Connection 4 | 5 | with Connection('amqp://guest:guest@localhost:5672//') as conn: 6 | simple_queue = conn.SimpleQueue('simple_queue') 7 | message = simple_queue.get(block=True, timeout=1) 8 | print(f'Received: {message.payload}') 9 | message.ack() 10 | simple_queue.close() 11 | -------------------------------------------------------------------------------- /examples/hello_publisher.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import datetime 4 | 5 | from kombu import Connection 6 | 7 | with Connection('amqp://guest:guest@localhost:5672//') as conn: 8 | simple_queue = conn.SimpleQueue('simple_queue') 9 | message = f'helloworld, sent at {datetime.datetime.today()}' 10 | simple_queue.put(message) 11 | print(f'Sent: {message}') 12 | simple_queue.close() 13 | -------------------------------------------------------------------------------- /examples/memory_transport.py: -------------------------------------------------------------------------------- 1 | """ 2 | Example that use memory transport for message produce. 3 | """ 4 | from __future__ import annotations 5 | 6 | import time 7 | 8 | from kombu import Connection, Consumer, Exchange, Queue 9 | 10 | media_exchange = Exchange('media', 'direct') 11 | video_queue = Queue('video', exchange=media_exchange, routing_key='video') 12 | task_queues = [video_queue] 13 | 14 | 15 | def handle_message(body, message): 16 | print(f"{time.time()} RECEIVED MESSAGE: {body!r}") 17 | message.ack() 18 | 19 | 20 | connection = Connection("memory:///") 21 | consumer = Consumer(connection, task_queues, callbacks=[handle_message]) 22 | 23 | producer = connection.Producer(serializer='json') 24 | producer.publish( 25 | {"foo": "bar"}, 26 | exchange=media_exchange, 27 | routing_key='video', 28 | declare=task_queues, 29 | ) 30 | consumer.consume() 31 | connection.drain_events() 32 | -------------------------------------------------------------------------------- /examples/rpc-tut6/rpc_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from __future__ import annotations 4 | 5 | from kombu import Connection, Consumer, Producer, Queue, uuid 6 | 7 | 8 | class FibonacciRpcClient: 9 | 10 | def __init__(self, connection): 11 | self.connection = connection 12 | self.callback_queue = Queue(uuid(), exclusive=True, auto_delete=True) 13 | 14 | def on_response(self, message): 15 | if message.properties['correlation_id'] == self.correlation_id: 16 | self.response = message.payload['result'] 17 | 18 | def call(self, n): 19 | self.response = None 20 | self.correlation_id = uuid() 21 | with Producer(self.connection) as producer: 22 | producer.publish( 23 | {'n': n}, 24 | exchange='', 25 | routing_key='rpc_queue', 26 | declare=[self.callback_queue], 27 | reply_to=self.callback_queue.name, 28 | correlation_id=self.correlation_id, 29 | ) 30 | with Consumer(self.connection, 31 | on_message=self.on_response, 32 | queues=[self.callback_queue], no_ack=True): 33 | while self.response is None: 34 | self.connection.drain_events() 35 | return self.response 36 | 37 | 38 | def main(broker_url): 39 | connection = Connection(broker_url) 40 | fibonacci_rpc = FibonacciRpcClient(connection) 41 | print(' [x] Requesting fib(30)') 42 | response = fibonacci_rpc.call(30) 43 | print(f' [.] Got {response!r}') 44 | 45 | 46 | if __name__ == '__main__': 47 | main('pyamqp://') 48 | -------------------------------------------------------------------------------- /examples/rpc-tut6/rpc_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from __future__ import annotations 4 | 5 | from kombu import Connection, Queue 6 | from kombu.mixins import ConsumerProducerMixin 7 | 8 | rpc_queue = Queue('rpc_queue') 9 | 10 | 11 | def fib(n): 12 | if n == 0: 13 | return 0 14 | elif n == 1: 15 | return 1 16 | else: 17 | return fib(n - 1) + fib(n - 2) 18 | 19 | 20 | class Worker(ConsumerProducerMixin): 21 | 22 | def __init__(self, connection): 23 | self.connection = connection 24 | 25 | def get_consumers(self, Consumer, channel): 26 | return [Consumer( 27 | queues=[rpc_queue], 28 | on_message=self.on_request, 29 | accept={'application/json'}, 30 | prefetch_count=1, 31 | )] 32 | 33 | def on_request(self, message): 34 | n = message.payload['n'] 35 | print(f' [.] fib({n})') 36 | result = fib(n) 37 | 38 | self.producer.publish( 39 | {'result': result}, 40 | exchange='', routing_key=message.properties['reply_to'], 41 | correlation_id=message.properties['correlation_id'], 42 | serializer='json', 43 | retry=True, 44 | ) 45 | message.ack() 46 | 47 | 48 | def start_worker(broker_url): 49 | connection = Connection(broker_url) 50 | print(' [x] Awaiting RPC requests') 51 | worker = Worker(connection) 52 | worker.run() 53 | 54 | 55 | if __name__ == '__main__': 56 | try: 57 | start_worker('pyamqp://') 58 | except KeyboardInterrupt: 59 | pass 60 | -------------------------------------------------------------------------------- /examples/simple_eventlet_receive.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Example that sends a single message and exits using the simple interface. 4 | 5 | You can use `simple_receive.py` (or `complete_receive.py`) to receive the 6 | message sent. 7 | 8 | """ 9 | 10 | from __future__ import annotations 11 | 12 | import eventlet 13 | 14 | from kombu import Connection 15 | 16 | eventlet.monkey_patch() 17 | 18 | 19 | def wait_many(timeout=1): 20 | 21 | #: Create connection 22 | #: If hostname, userid, password and virtual_host is not specified 23 | #: the values below are the default, but listed here so it can 24 | #: be easily changed. 25 | with Connection('amqp://guest:guest@localhost:5672//') as connection: 26 | 27 | #: SimpleQueue mimics the interface of the Python Queue module. 28 | #: First argument can either be a queue name or a kombu.Queue object. 29 | #: If a name, then the queue will be declared with the name as the 30 | #: queue name, exchange name and routing key. 31 | with connection.SimpleQueue('kombu_demo') as queue: 32 | 33 | while True: 34 | try: 35 | message = queue.get(block=False, timeout=timeout) 36 | except queue.Empty: 37 | break 38 | else: 39 | message.ack() 40 | print(message.payload) 41 | 42 | 43 | eventlet.spawn(wait_many).wait() 44 | -------------------------------------------------------------------------------- /examples/simple_eventlet_send.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Example that sends a single message and exits using the simple interface. 4 | 5 | You can use `simple_receive.py` (or `complete_receive.py`) to receive the 6 | message sent. 7 | 8 | """ 9 | 10 | from __future__ import annotations 11 | 12 | import eventlet 13 | 14 | from kombu import Connection 15 | 16 | eventlet.monkey_patch() 17 | 18 | 19 | def send_many(n): 20 | 21 | #: Create connection 22 | #: If hostname, userid, password and virtual_host is not specified 23 | #: the values below are the default, but listed here so it can 24 | #: be easily changed. 25 | with Connection('amqp://guest:guest@localhost:5672//') as connection: 26 | 27 | #: SimpleQueue mimics the interface of the Python Queue module. 28 | #: First argument can either be a queue name or a kombu.Queue object. 29 | #: If a name, then the queue will be declared with the name as the 30 | #: queue name, exchange name and routing key. 31 | with connection.SimpleQueue('kombu_demo') as queue: 32 | 33 | def send_message(i): 34 | queue.put({'hello': f'world{i}'}) 35 | 36 | pool = eventlet.GreenPool(10) 37 | for i in range(n): 38 | pool.spawn(send_message, i) 39 | pool.waitall() 40 | 41 | 42 | if __name__ == '__main__': 43 | send_many(10) 44 | -------------------------------------------------------------------------------- /examples/simple_receive.py: -------------------------------------------------------------------------------- 1 | """ 2 | Example receiving a message using the SimpleQueue interface. 3 | 4 | """ 5 | 6 | from __future__ import annotations 7 | 8 | from kombu import Connection 9 | 10 | #: Create connection 11 | #: If hostname, userid, password and virtual_host is not specified 12 | #: the values below are the default, but listed here so it can 13 | #: be easily changed. 14 | with Connection('amqp://guest:guest@localhost:5672//') as conn: 15 | 16 | #: SimpleQueue mimics the interface of the Python Queue module. 17 | #: First argument can either be a queue name or a kombu.Queue object. 18 | #: If a name, then the queue will be declared with the name as the queue 19 | #: name, exchange name and routing key. 20 | with conn.SimpleQueue('kombu_demo') as queue: 21 | message = queue.get(block=True, timeout=10) 22 | message.ack() 23 | print(message.payload) 24 | 25 | #### 26 | #: If you don't use the with statement then you must always 27 | # remember to close objects after use: 28 | # queue.close() 29 | # connection.close() 30 | -------------------------------------------------------------------------------- /examples/simple_send.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Example that sends a single message and exits using the simple interface. 4 | 5 | You can use `simple_receive.py` (or `complete_receive.py`) to receive the 6 | message sent. 7 | 8 | """ 9 | 10 | from __future__ import annotations 11 | 12 | from kombu import Connection 13 | 14 | #: Create connection 15 | #: If hostname, userid, password and virtual_host is not specified 16 | #: the values below are the default, but listed here so it can 17 | #: be easily changed. 18 | with Connection('amqp://guest:guest@localhost:5672//') as conn: 19 | 20 | #: SimpleQueue mimics the interface of the Python Queue module. 21 | #: First argument can either be a queue name or a kombu.Queue object. 22 | #: If a name, then the queue will be declared with the name as the queue 23 | #: name, exchange name and routing key. 24 | with conn.SimpleQueue('kombu_demo') as queue: 25 | queue.put({'hello': 'world'}, serializer='json', compression='zlib') 26 | 27 | 28 | ##### 29 | # If you don't use the with statement, you must always 30 | # remember to close objects. 31 | # queue.close() 32 | # connection.close() 33 | -------------------------------------------------------------------------------- /examples/simple_task_queue/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/examples/simple_task_queue/__init__.py -------------------------------------------------------------------------------- /examples/simple_task_queue/client.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from kombu.pools import producers 4 | 5 | from .queues import task_exchange 6 | 7 | priority_to_routing_key = { 8 | 'high': 'hipri', 9 | 'mid': 'midpri', 10 | 'low': 'lopri', 11 | } 12 | 13 | 14 | def send_as_task(connection, fun, args=(), kwargs={}, priority='mid'): 15 | payload = {'fun': fun, 'args': args, 'kwargs': kwargs} 16 | routing_key = priority_to_routing_key[priority] 17 | 18 | with producers[connection].acquire(block=True) as producer: 19 | producer.publish(payload, 20 | serializer='pickle', 21 | compression='bzip2', 22 | exchange=task_exchange, 23 | declare=[task_exchange], 24 | routing_key=routing_key) 25 | 26 | 27 | if __name__ == '__main__': 28 | from kombu import Connection 29 | 30 | from .tasks import hello_task 31 | 32 | connection = Connection('amqp://guest:guest@localhost:5672//') 33 | send_as_task(connection, fun=hello_task, args=('Kombu',), kwargs={}, 34 | priority='high') 35 | -------------------------------------------------------------------------------- /examples/simple_task_queue/queues.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from kombu import Exchange, Queue 4 | 5 | task_exchange = Exchange('tasks', type='direct') 6 | task_queues = [Queue('hipri', task_exchange, routing_key='hipri'), 7 | Queue('midpri', task_exchange, routing_key='midpri'), 8 | Queue('lopri', task_exchange, routing_key='lopri')] 9 | -------------------------------------------------------------------------------- /examples/simple_task_queue/tasks.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | 4 | def hello_task(who='world'): 5 | print(f'Hello {who}') 6 | -------------------------------------------------------------------------------- /examples/simple_task_queue/worker.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from kombu.log import get_logger 4 | from kombu.mixins import ConsumerMixin 5 | from kombu.utils.functional import reprcall 6 | 7 | from .queues import task_queues 8 | 9 | logger = get_logger(__name__) 10 | 11 | 12 | class Worker(ConsumerMixin): 13 | 14 | def __init__(self, connection): 15 | self.connection = connection 16 | 17 | def get_consumers(self, Consumer, channel): 18 | return [Consumer(queues=task_queues, 19 | accept=['pickle', 'json'], 20 | callbacks=[self.process_task])] 21 | 22 | def process_task(self, body, message): 23 | fun = body['fun'] 24 | args = body['args'] 25 | kwargs = body['kwargs'] 26 | logger.info('Got task: %s', reprcall(fun.__name__, args, kwargs)) 27 | try: 28 | fun(*args, **kwargs) 29 | except Exception as exc: 30 | logger.error('task raised exception: %r', exc) 31 | message.ack() 32 | 33 | 34 | if __name__ == '__main__': 35 | from kombu import Connection 36 | from kombu.utils.debug import setup_logging 37 | 38 | # setup root logger 39 | setup_logging(loglevel='INFO', loggers=['']) 40 | 41 | with Connection('amqp://guest:guest@localhost:5672//') as conn: 42 | try: 43 | worker = Worker(conn) 44 | worker.run() 45 | except KeyboardInterrupt: 46 | print('bye bye') 47 | -------------------------------------------------------------------------------- /kombu/asynchronous/__init__.py: -------------------------------------------------------------------------------- 1 | """Event loop.""" 2 | 3 | from __future__ import annotations 4 | 5 | from kombu.utils.eventio import ERR, READ, WRITE 6 | 7 | from .hub import Hub, get_event_loop, set_event_loop 8 | 9 | __all__ = ('READ', 'WRITE', 'ERR', 'Hub', 'get_event_loop', 'set_event_loop') 10 | -------------------------------------------------------------------------------- /kombu/asynchronous/aws/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import Any 4 | 5 | from kombu.asynchronous.aws.sqs.connection import AsyncSQSConnection 6 | 7 | 8 | def connect_sqs( 9 | aws_access_key_id: str | None = None, 10 | aws_secret_access_key: str | None = None, 11 | **kwargs: Any 12 | ) -> AsyncSQSConnection: 13 | """Return async connection to Amazon SQS.""" 14 | from .sqs.connection import AsyncSQSConnection 15 | return AsyncSQSConnection( 16 | aws_access_key_id, aws_secret_access_key, **kwargs 17 | ) 18 | -------------------------------------------------------------------------------- /kombu/asynchronous/aws/ext.py: -------------------------------------------------------------------------------- 1 | """Amazon boto3 interface.""" 2 | 3 | from __future__ import annotations 4 | 5 | try: 6 | import boto3 7 | from botocore import exceptions 8 | from botocore.awsrequest import AWSRequest 9 | from botocore.httpsession import get_cert_path 10 | from botocore.response import get_response 11 | except ImportError: 12 | boto3 = None 13 | 14 | class _void: 15 | pass 16 | 17 | class BotoCoreError(Exception): 18 | pass 19 | exceptions = _void() 20 | exceptions.BotoCoreError = BotoCoreError 21 | AWSRequest = _void() 22 | get_response = _void() 23 | get_cert_path = _void() 24 | 25 | 26 | __all__ = ( 27 | 'exceptions', 'AWSRequest', 'get_response', 'get_cert_path', 28 | ) 29 | -------------------------------------------------------------------------------- /kombu/asynchronous/aws/sqs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/kombu/asynchronous/aws/sqs/__init__.py -------------------------------------------------------------------------------- /kombu/asynchronous/aws/sqs/ext.py: -------------------------------------------------------------------------------- 1 | """Amazon SQS boto3 interface.""" 2 | 3 | 4 | from __future__ import annotations 5 | 6 | try: 7 | import boto3 8 | except ImportError: 9 | boto3 = None 10 | -------------------------------------------------------------------------------- /kombu/asynchronous/aws/sqs/message.py: -------------------------------------------------------------------------------- 1 | """Amazon SQS message implementation.""" 2 | 3 | from __future__ import annotations 4 | 5 | import base64 6 | 7 | from kombu.message import Message 8 | from kombu.utils.encoding import str_to_bytes 9 | 10 | 11 | class BaseAsyncMessage(Message): 12 | """Base class for messages received on async client.""" 13 | 14 | 15 | class AsyncRawMessage(BaseAsyncMessage): 16 | """Raw Message.""" 17 | 18 | 19 | class AsyncMessage(BaseAsyncMessage): 20 | """Serialized message.""" 21 | 22 | def encode(self, value): 23 | """Encode/decode the value using Base64 encoding.""" 24 | return base64.b64encode(str_to_bytes(value)).decode() 25 | 26 | def __getitem__(self, item): 27 | """Support Boto3-style access on a message.""" 28 | if item == 'ReceiptHandle': 29 | return self.receipt_handle 30 | elif item == 'Body': 31 | return self.get_body() 32 | elif item == 'queue': 33 | return self.queue 34 | else: 35 | raise KeyError(item) 36 | -------------------------------------------------------------------------------- /kombu/asynchronous/debug.py: -------------------------------------------------------------------------------- 1 | """Event-loop debugging tools.""" 2 | 3 | from __future__ import annotations 4 | 5 | from kombu.utils.eventio import ERR, READ, WRITE 6 | from kombu.utils.functional import reprcall 7 | 8 | 9 | def repr_flag(flag): 10 | """Return description of event loop flag.""" 11 | return '{}{}{}'.format('R' if flag & READ else '', 12 | 'W' if flag & WRITE else '', 13 | '!' if flag & ERR else '') 14 | 15 | 16 | def _rcb(obj): 17 | if obj is None: 18 | return '' 19 | if isinstance(obj, str): 20 | return obj 21 | if isinstance(obj, tuple): 22 | cb, args = obj 23 | return reprcall(cb.__name__, args=args) 24 | return obj.__name__ 25 | 26 | 27 | def repr_active(h): 28 | """Return description of active readers and writers.""" 29 | return ', '.join(repr_readers(h) + repr_writers(h)) 30 | 31 | 32 | def repr_events(h, events): 33 | """Return description of events returned by poll.""" 34 | return ', '.join( 35 | '{}({})->{}'.format( 36 | _rcb(callback_for(h, fd, fl, '(GONE)')), fd, 37 | repr_flag(fl), 38 | ) 39 | for fd, fl in events 40 | ) 41 | 42 | 43 | def repr_readers(h): 44 | """Return description of pending readers.""" 45 | return [f'({fd}){_rcb(cb)}->{repr_flag(READ | ERR)}' 46 | for fd, cb in h.readers.items()] 47 | 48 | 49 | def repr_writers(h): 50 | """Return description of pending writers.""" 51 | return [f'({fd}){_rcb(cb)}->{repr_flag(WRITE)}' 52 | for fd, cb in h.writers.items()] 53 | 54 | 55 | def callback_for(h, fd, flag, *default): 56 | """Return the callback used for hub+fd+flag.""" 57 | try: 58 | if flag & READ: 59 | return h.readers[fd] 60 | if flag & WRITE: 61 | if fd in h.consolidate: 62 | return h.consolidate_callback 63 | return h.writers[fd] 64 | except KeyError: 65 | if default: 66 | return default[0] 67 | raise 68 | -------------------------------------------------------------------------------- /kombu/asynchronous/http/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from kombu.asynchronous import get_event_loop 4 | from kombu.asynchronous.http.base import BaseClient, Headers, Request, Response 5 | from kombu.asynchronous.hub import Hub 6 | 7 | __all__ = ('Client', 'Headers', 'Response', 'Request', 'get_client') 8 | 9 | 10 | def Client(hub: Hub | None = None, **kwargs: int) -> BaseClient: 11 | """Create new HTTP client.""" 12 | from .urllib3_client import Urllib3Client 13 | return Urllib3Client(hub, **kwargs) 14 | 15 | 16 | def get_client(hub: Hub | None = None, **kwargs: int) -> BaseClient: 17 | """Get or create HTTP client bound to the current event loop.""" 18 | hub = hub or get_event_loop() 19 | try: 20 | return hub._current_http_client 21 | except AttributeError: 22 | client = hub._current_http_client = Client(hub, **kwargs) 23 | return client 24 | -------------------------------------------------------------------------------- /kombu/compression.py: -------------------------------------------------------------------------------- 1 | """Compression utilities.""" 2 | 3 | from __future__ import annotations 4 | 5 | import zlib 6 | 7 | from kombu.utils.encoding import ensure_bytes 8 | 9 | _aliases = {} 10 | _encoders = {} 11 | _decoders = {} 12 | 13 | __all__ = ('register', 'encoders', 'get_encoder', 14 | 'get_decoder', 'compress', 'decompress') 15 | 16 | 17 | def register(encoder, decoder, content_type, aliases=None): 18 | """Register new compression method. 19 | 20 | Arguments: 21 | --------- 22 | encoder (Callable): Function used to compress text. 23 | decoder (Callable): Function used to decompress previously 24 | compressed text. 25 | content_type (str): The mime type this compression method 26 | identifies as. 27 | aliases (Sequence[str]): A list of names to associate with 28 | this compression method. 29 | """ 30 | _encoders[content_type] = encoder 31 | _decoders[content_type] = decoder 32 | if aliases: 33 | _aliases.update((alias, content_type) for alias in aliases) 34 | 35 | 36 | def encoders(): 37 | """Return a list of available compression methods.""" 38 | return list(_encoders) 39 | 40 | 41 | def get_encoder(t): 42 | """Get encoder by alias name.""" 43 | t = _aliases.get(t, t) 44 | return _encoders[t], t 45 | 46 | 47 | def get_decoder(t): 48 | """Get decoder by alias name.""" 49 | return _decoders[_aliases.get(t, t)] 50 | 51 | 52 | def compress(body, content_type): 53 | """Compress text. 54 | 55 | Arguments: 56 | --------- 57 | body (AnyStr): The text to compress. 58 | content_type (str): mime-type of compression method to use. 59 | """ 60 | encoder, content_type = get_encoder(content_type) 61 | return encoder(ensure_bytes(body)), content_type 62 | 63 | 64 | def decompress(body, content_type): 65 | """Decompress compressed text. 66 | 67 | Arguments: 68 | --------- 69 | body (AnyStr): Previously compressed text to uncompress. 70 | content_type (str): mime-type of compression method used. 71 | """ 72 | return get_decoder(content_type)(body) 73 | 74 | 75 | register(zlib.compress, 76 | zlib.decompress, 77 | 'application/x-gzip', aliases=['gzip', 'zlib']) 78 | 79 | try: 80 | import bz2 81 | except ImportError: # pragma: no cover 82 | pass # No bz2 support 83 | else: 84 | register(bz2.compress, 85 | bz2.decompress, 86 | 'application/x-bz2', aliases=['bzip2', 'bzip']) 87 | 88 | try: 89 | import brotli 90 | except ImportError: # pragma: no cover 91 | pass 92 | else: 93 | register(brotli.compress, 94 | brotli.decompress, 95 | 'application/x-brotli', aliases=['brotli']) 96 | 97 | try: 98 | import lzma 99 | except ImportError: # pragma: no cover 100 | pass # no lzma support 101 | else: 102 | register(lzma.compress, 103 | lzma.decompress, 104 | 'application/x-lzma', aliases=['lzma', 'xz']) 105 | 106 | try: 107 | import zstandard as zstd 108 | except ImportError: # pragma: no cover 109 | pass 110 | else: 111 | def zstd_compress(body): 112 | c = zstd.ZstdCompressor() 113 | return c.compress(body) 114 | 115 | def zstd_decompress(body): 116 | d = zstd.ZstdDecompressor() 117 | return d.decompress(body) 118 | 119 | register(zstd_compress, 120 | zstd_decompress, 121 | 'application/zstd', aliases=['zstd', 'zstandard']) 122 | -------------------------------------------------------------------------------- /kombu/exceptions.py: -------------------------------------------------------------------------------- 1 | """Exceptions.""" 2 | 3 | from __future__ import annotations 4 | 5 | from socket import timeout as TimeoutError 6 | from types import TracebackType 7 | from typing import TYPE_CHECKING, TypeVar 8 | 9 | from amqp import ChannelError, ConnectionError, ResourceError 10 | 11 | if TYPE_CHECKING: 12 | from kombu.asynchronous.http import Response 13 | 14 | __all__ = ( 15 | 'reraise', 'KombuError', 'OperationalError', 16 | 'NotBoundError', 'MessageStateError', 'TimeoutError', 17 | 'LimitExceeded', 'ConnectionLimitExceeded', 18 | 'ChannelLimitExceeded', 'ConnectionError', 'ChannelError', 19 | 'VersionMismatch', 'SerializerNotInstalled', 'ResourceError', 20 | 'SerializationError', 'EncodeError', 'DecodeError', 'HttpError', 21 | 'InconsistencyError', 22 | ) 23 | 24 | BaseExceptionType = TypeVar('BaseExceptionType', bound=BaseException) 25 | 26 | 27 | def reraise( 28 | tp: type[BaseExceptionType], 29 | value: BaseExceptionType, 30 | tb: TracebackType | None = None 31 | ) -> BaseExceptionType: 32 | """Reraise exception.""" 33 | if value.__traceback__ is not tb: 34 | raise value.with_traceback(tb) 35 | raise value 36 | 37 | 38 | class KombuError(Exception): 39 | """Common subclass for all Kombu exceptions.""" 40 | 41 | 42 | class OperationalError(KombuError): 43 | """Recoverable message transport connection error.""" 44 | 45 | 46 | class SerializationError(KombuError): 47 | """Failed to serialize/deserialize content.""" 48 | 49 | 50 | class EncodeError(SerializationError): 51 | """Cannot encode object.""" 52 | 53 | 54 | class DecodeError(SerializationError): 55 | """Cannot decode object.""" 56 | 57 | 58 | class NotBoundError(KombuError): 59 | """Trying to call channel dependent method on unbound entity.""" 60 | 61 | 62 | class MessageStateError(KombuError): 63 | """The message has already been acknowledged.""" 64 | 65 | 66 | class LimitExceeded(KombuError): 67 | """Limit exceeded.""" 68 | 69 | 70 | class ConnectionLimitExceeded(LimitExceeded): 71 | """Maximum number of simultaneous connections exceeded.""" 72 | 73 | 74 | class ChannelLimitExceeded(LimitExceeded): 75 | """Maximum number of simultaneous channels exceeded.""" 76 | 77 | 78 | class VersionMismatch(KombuError): 79 | """Library dependency version mismatch.""" 80 | 81 | 82 | class SerializerNotInstalled(KombuError): 83 | """Support for the requested serialization type is not installed.""" 84 | 85 | 86 | class ContentDisallowed(SerializerNotInstalled): 87 | """Consumer does not allow this content-type.""" 88 | 89 | 90 | class InconsistencyError(ConnectionError): 91 | """Data or environment has been found to be inconsistent. 92 | 93 | Depending on the cause it may be possible to retry the operation. 94 | """ 95 | 96 | 97 | class HttpError(Exception): 98 | """HTTP Client Error.""" 99 | 100 | def __init__( 101 | self, 102 | code: int, 103 | message: str | None = None, 104 | response: Response | None = None 105 | ) -> None: 106 | self.code = code 107 | self.message = message 108 | self.response = response 109 | super().__init__(code, message, response) 110 | 111 | def __str__(self) -> str: 112 | return 'HTTP {0.code}: {0.message}'.format(self) 113 | -------------------------------------------------------------------------------- /kombu/transport/memory.py: -------------------------------------------------------------------------------- 1 | """In-memory transport module for Kombu. 2 | 3 | Simple transport using memory for storing messages. 4 | Messages can be passed only between threads. 5 | 6 | Features 7 | ======== 8 | * Type: Virtual 9 | * Supports Direct: Yes 10 | * Supports Topic: Yes 11 | * Supports Fanout: No 12 | * Supports Priority: No 13 | * Supports TTL: Yes 14 | 15 | Connection String 16 | ================= 17 | Connection string is in the following format: 18 | 19 | .. code-block:: 20 | 21 | memory:// 22 | 23 | """ 24 | 25 | from __future__ import annotations 26 | 27 | from collections import defaultdict 28 | from queue import Queue 29 | 30 | from . import base, virtual 31 | 32 | 33 | class Channel(virtual.Channel): 34 | """In-memory Channel.""" 35 | 36 | events = defaultdict(set) 37 | queues = {} 38 | do_restore = False 39 | supports_fanout = True 40 | 41 | def _has_queue(self, queue, **kwargs): 42 | return queue in self.queues 43 | 44 | def _new_queue(self, queue, **kwargs): 45 | if queue not in self.queues: 46 | self.queues[queue] = Queue() 47 | 48 | def _get(self, queue, timeout=None): 49 | return self._queue_for(queue).get(block=False) 50 | 51 | def _queue_for(self, queue): 52 | if queue not in self.queues: 53 | self.queues[queue] = Queue() 54 | return self.queues[queue] 55 | 56 | def _queue_bind(self, *args): 57 | pass 58 | 59 | def _put_fanout(self, exchange, message, routing_key=None, **kwargs): 60 | for queue in self._lookup(exchange, routing_key): 61 | self._queue_for(queue).put(message) 62 | 63 | def _put(self, queue, message, **kwargs): 64 | self._queue_for(queue).put(message) 65 | 66 | def _size(self, queue): 67 | return self._queue_for(queue).qsize() 68 | 69 | def _delete(self, queue, *args, **kwargs): 70 | self.queues.pop(queue, None) 71 | 72 | def _purge(self, queue): 73 | q = self._queue_for(queue) 74 | size = q.qsize() 75 | q.queue.clear() 76 | return size 77 | 78 | def close(self): 79 | super().close() 80 | for queue in self.queues.values(): 81 | queue.empty() 82 | self.queues = {} 83 | 84 | def after_reply_message_received(self, queue): 85 | pass 86 | 87 | 88 | class Transport(virtual.Transport): 89 | """In-memory Transport.""" 90 | 91 | Channel = Channel 92 | 93 | #: memory backend state is global. 94 | global_state = virtual.BrokerState() 95 | 96 | implements = base.Transport.implements 97 | 98 | driver_type = 'memory' 99 | driver_name = 'memory' 100 | 101 | def __init__(self, client, **kwargs): 102 | super().__init__(client, **kwargs) 103 | self.state = self.global_state 104 | 105 | def driver_version(self): 106 | return 'N/A' 107 | -------------------------------------------------------------------------------- /kombu/transport/sqlalchemy/models.py: -------------------------------------------------------------------------------- 1 | """Kombu transport using SQLAlchemy as the message store.""" 2 | 3 | from __future__ import annotations 4 | 5 | import datetime 6 | 7 | from sqlalchemy import (Boolean, Column, DateTime, ForeignKey, Index, Integer, 8 | Sequence, SmallInteger, String, Text) 9 | from sqlalchemy.orm import relationship 10 | from sqlalchemy.schema import MetaData 11 | 12 | try: 13 | from sqlalchemy.orm import declarative_base, declared_attr 14 | except ImportError: 15 | # TODO: Remove this once we drop support for SQLAlchemy < 1.4. 16 | from sqlalchemy.ext.declarative import declarative_base, declared_attr 17 | 18 | class_registry = {} 19 | metadata = MetaData() 20 | ModelBase = declarative_base(metadata=metadata, class_registry=class_registry) 21 | 22 | 23 | class Queue: 24 | """The queue class.""" 25 | 26 | __table_args__ = {'sqlite_autoincrement': True, 'mysql_engine': 'InnoDB'} 27 | 28 | id = Column(Integer, Sequence('queue_id_sequence'), primary_key=True, 29 | autoincrement=True) 30 | name = Column(String(200), unique=True) 31 | 32 | def __init__(self, name): 33 | self.name = name 34 | 35 | def __str__(self): 36 | return f'' 37 | 38 | @declared_attr 39 | def messages(cls): 40 | return relationship('Message', backref='queue', lazy='noload') 41 | 42 | 43 | class Message: 44 | """The message class.""" 45 | 46 | __table_args__ = ( 47 | Index('ix_kombu_message_timestamp_id', 'timestamp', 'id'), 48 | {'sqlite_autoincrement': True, 'mysql_engine': 'InnoDB'} 49 | ) 50 | 51 | id = Column(Integer, Sequence('message_id_sequence'), 52 | primary_key=True, autoincrement=True) 53 | visible = Column(Boolean, default=True, index=True) 54 | sent_at = Column('timestamp', DateTime, nullable=True, index=True, 55 | onupdate=datetime.datetime.now) 56 | payload = Column(Text, nullable=False) 57 | version = Column(SmallInteger, nullable=False, default=1) 58 | 59 | __mapper_args__ = {'version_id_col': version} 60 | 61 | def __init__(self, payload, queue): 62 | self.payload = payload 63 | self.queue = queue 64 | 65 | def __str__(self): 66 | return ''.format(self) 67 | 68 | @declared_attr 69 | def queue_id(self): 70 | return Column( 71 | Integer, 72 | ForeignKey( 73 | '%s.id' % class_registry['Queue'].__tablename__, 74 | name='FK_kombu_message_queue' 75 | ) 76 | ) 77 | -------------------------------------------------------------------------------- /kombu/transport/virtual/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from .base import (AbstractChannel, Base64, BrokerState, Channel, Empty, 4 | Management, Message, NotEquivalentError, QoS, Transport, 5 | UndeliverableWarning, binding_key_t, queue_binding_t) 6 | 7 | __all__ = ( 8 | 'Base64', 'NotEquivalentError', 'UndeliverableWarning', 'BrokerState', 9 | 'QoS', 'Message', 'AbstractChannel', 'Channel', 'Management', 'Transport', 10 | 'Empty', 'binding_key_t', 'queue_binding_t', 11 | ) 12 | -------------------------------------------------------------------------------- /kombu/utils/__init__.py: -------------------------------------------------------------------------------- 1 | """DEPRECATED - Import from modules below.""" 2 | 3 | from __future__ import annotations 4 | 5 | from .collections import EqualityDict 6 | from .compat import fileno, maybe_fileno, nested, register_after_fork 7 | from .div import emergency_dump_state 8 | from .functional import (fxrange, fxrangemax, maybe_list, reprcall, 9 | retry_over_time) 10 | from .imports import symbol_by_name 11 | from .objects import cached_property 12 | from .uuid import uuid 13 | 14 | __all__ = ( 15 | 'EqualityDict', 'uuid', 'maybe_list', 16 | 'fxrange', 'fxrangemax', 'retry_over_time', 17 | 'emergency_dump_state', 'cached_property', 18 | 'register_after_fork', 'reprkwargs', 'reprcall', 19 | 'symbol_by_name', 'nested', 'fileno', 'maybe_fileno', 20 | ) 21 | -------------------------------------------------------------------------------- /kombu/utils/amq_manager.py: -------------------------------------------------------------------------------- 1 | """AMQP Management API utilities.""" 2 | 3 | 4 | from __future__ import annotations 5 | 6 | 7 | def get_manager(client, hostname=None, port=None, userid=None, 8 | password=None): 9 | """Get pyrabbit manager.""" 10 | import pyrabbit 11 | opt = client.transport_options.get 12 | 13 | def get(name, val, default): 14 | return (val if val is not None 15 | else opt('manager_%s' % name) or 16 | getattr(client, name, None) or default) 17 | 18 | host = get('hostname', hostname, 'localhost') 19 | port = port if port is not None else opt('manager_port', 15672) 20 | userid = get('userid', userid, 'guest') 21 | password = get('password', password, 'guest') 22 | return pyrabbit.Client(f'{host}:{port}', userid, password) 23 | -------------------------------------------------------------------------------- /kombu/utils/collections.py: -------------------------------------------------------------------------------- 1 | """Custom maps, sequences, etc.""" 2 | 3 | 4 | from __future__ import annotations 5 | 6 | 7 | class HashedSeq(list): 8 | """Hashed Sequence. 9 | 10 | Type used for hash() to make sure the hash is not generated 11 | multiple times. 12 | """ 13 | 14 | __slots__ = 'hashvalue' 15 | 16 | def __init__(self, *seq): 17 | self[:] = seq 18 | self.hashvalue = hash(seq) 19 | 20 | def __hash__(self): 21 | return self.hashvalue 22 | 23 | 24 | def eqhash(o): 25 | """Call ``obj.__eqhash__``.""" 26 | try: 27 | return o.__eqhash__() 28 | except AttributeError: 29 | return hash(o) 30 | 31 | 32 | class EqualityDict(dict): 33 | """Dict using the eq operator for keying.""" 34 | 35 | def __getitem__(self, key): 36 | h = eqhash(key) 37 | if h not in self: 38 | return self.__missing__(key) 39 | return super().__getitem__(h) 40 | 41 | def __setitem__(self, key, value): 42 | return super().__setitem__(eqhash(key), value) 43 | 44 | def __delitem__(self, key): 45 | return super().__delitem__(eqhash(key)) 46 | -------------------------------------------------------------------------------- /kombu/utils/debug.py: -------------------------------------------------------------------------------- 1 | """Debugging support.""" 2 | 3 | from __future__ import annotations 4 | 5 | import logging 6 | from typing import TYPE_CHECKING 7 | 8 | from vine.utils import wraps 9 | 10 | from kombu.log import get_logger 11 | 12 | if TYPE_CHECKING: 13 | from logging import Logger 14 | from typing import Any, Callable 15 | 16 | from kombu.transport.base import Transport 17 | 18 | __all__ = ('setup_logging', 'Logwrapped') 19 | 20 | 21 | def setup_logging( 22 | loglevel: int | None = logging.DEBUG, 23 | loggers: list[str] | None = None 24 | ) -> None: 25 | """Setup logging to stdout.""" 26 | loggers = ['kombu.connection', 'kombu.channel'] if not loggers else loggers 27 | for logger_name in loggers: 28 | logger = get_logger(logger_name) 29 | logger.addHandler(logging.StreamHandler()) 30 | logger.setLevel(loglevel) 31 | 32 | 33 | class Logwrapped: 34 | """Wrap all object methods, to log on call.""" 35 | 36 | __ignore = ('__enter__', '__exit__') 37 | 38 | def __init__( 39 | self, 40 | instance: Transport, 41 | logger: Logger | None = None, 42 | ident: str | None = None 43 | ): 44 | self.instance = instance 45 | self.logger = get_logger(logger) 46 | self.ident = ident 47 | 48 | def __getattr__(self, key: str) -> Callable: 49 | meth = getattr(self.instance, key) 50 | 51 | if not callable(meth) or key in self.__ignore: 52 | return meth 53 | 54 | @wraps(meth) 55 | def __wrapped(*args: list[Any], **kwargs: dict[str, Any]) -> Callable: 56 | info = '' 57 | if self.ident: 58 | info += self.ident.format(self.instance) 59 | info += f'{meth.__name__}(' 60 | if args: 61 | info += ', '.join(map(repr, args)) 62 | if kwargs: 63 | if args: 64 | info += ', ' 65 | info += ', '.join(f'{key}={value!r}' 66 | for key, value in kwargs.items()) 67 | info += ')' 68 | self.logger.debug(info) 69 | return meth(*args, **kwargs) 70 | 71 | return __wrapped 72 | 73 | def __repr__(self) -> str: 74 | return repr(self.instance) 75 | 76 | def __dir__(self) -> list[str]: 77 | return dir(self.instance) 78 | -------------------------------------------------------------------------------- /kombu/utils/div.py: -------------------------------------------------------------------------------- 1 | """Div. Utilities.""" 2 | 3 | from __future__ import annotations 4 | 5 | import os 6 | import sys 7 | 8 | from .encoding import default_encode 9 | 10 | 11 | def emergency_dump_state(state, open_file=open, dump=None, stderr=None): 12 | """Dump message state to stdout or file.""" 13 | from pprint import pformat 14 | from tempfile import mkstemp 15 | stderr = sys.stderr if stderr is None else stderr 16 | 17 | if dump is None: 18 | import pickle 19 | dump = pickle.dump 20 | fd, persist = mkstemp() 21 | os.close(fd) 22 | print(f'EMERGENCY DUMP STATE TO FILE -> {persist} <-', 23 | file=stderr) 24 | fh = open_file(persist, 'w') 25 | try: 26 | try: 27 | dump(state, fh, protocol=0) 28 | except Exception as exc: 29 | print( 30 | f'Cannot pickle state: {exc!r}. Fallback to pformat.', 31 | file=stderr, 32 | ) 33 | fh.write(default_encode(pformat(state))) 34 | finally: 35 | fh.flush() 36 | fh.close() 37 | return persist 38 | -------------------------------------------------------------------------------- /kombu/utils/encoding.py: -------------------------------------------------------------------------------- 1 | """Text encoding utilities. 2 | 3 | Utilities to encode text, and to safely emit text from running 4 | applications without crashing from the infamous 5 | :exc:`UnicodeDecodeError` exception. 6 | """ 7 | 8 | from __future__ import annotations 9 | 10 | import sys 11 | import traceback 12 | 13 | #: safe_str takes encoding from this file by default. 14 | #: :func:`set_default_encoding_file` can used to set the 15 | #: default output file. 16 | default_encoding_file = None 17 | 18 | 19 | def set_default_encoding_file(file): 20 | """Set file used to get codec information.""" 21 | global default_encoding_file 22 | default_encoding_file = file 23 | 24 | 25 | def get_default_encoding_file(): 26 | """Get file used to get codec information.""" 27 | return default_encoding_file 28 | 29 | 30 | if sys.platform.startswith('java'): # pragma: no cover 31 | 32 | def default_encoding(file=None): 33 | """Get default encoding.""" 34 | return 'utf-8' 35 | else: 36 | 37 | def default_encoding(file=None): 38 | """Get default encoding.""" 39 | file = file or get_default_encoding_file() 40 | return getattr(file, 'encoding', None) or sys.getfilesystemencoding() 41 | 42 | 43 | def str_to_bytes(s): 44 | """Convert str to bytes.""" 45 | if isinstance(s, str): 46 | return s.encode() 47 | return s 48 | 49 | 50 | def bytes_to_str(s): 51 | """Convert bytes to str.""" 52 | if isinstance(s, bytes): 53 | return s.decode(errors='replace') 54 | return s 55 | 56 | 57 | def from_utf8(s, *args, **kwargs): 58 | """Get str from utf-8 encoding.""" 59 | return s 60 | 61 | 62 | def ensure_bytes(s): 63 | """Ensure s is bytes, not str.""" 64 | if not isinstance(s, bytes): 65 | return str_to_bytes(s) 66 | return s 67 | 68 | 69 | def default_encode(obj): 70 | """Encode using default encoding.""" 71 | return obj 72 | 73 | 74 | def safe_str(s, errors='replace'): 75 | """Safe form of str(), void of unicode errors.""" 76 | s = bytes_to_str(s) 77 | if not isinstance(s, (str, bytes)): 78 | return safe_repr(s, errors) 79 | return _safe_str(s, errors) 80 | 81 | 82 | def _safe_str(s, errors='replace', file=None): 83 | if isinstance(s, str): 84 | return s 85 | try: 86 | return str(s) 87 | except Exception as exc: 88 | return ''.format( 89 | type(s), exc, '\n'.join(traceback.format_stack())) 90 | 91 | 92 | def safe_repr(o, errors='replace'): 93 | """Safe form of repr, void of Unicode errors.""" 94 | try: 95 | return repr(o) 96 | except Exception: 97 | return _safe_str(o, errors) 98 | -------------------------------------------------------------------------------- /kombu/utils/imports.py: -------------------------------------------------------------------------------- 1 | """Import related utilities.""" 2 | 3 | from __future__ import annotations 4 | 5 | import importlib 6 | import sys 7 | 8 | from kombu.exceptions import reraise 9 | 10 | 11 | def symbol_by_name(name, aliases=None, imp=None, package=None, 12 | sep='.', default=None, **kwargs): 13 | """Get symbol by qualified name. 14 | 15 | The name should be the full dot-separated path to the class:: 16 | 17 | modulename.ClassName 18 | 19 | Example:: 20 | 21 | celery.concurrency.processes.TaskPool 22 | ^- class name 23 | 24 | or using ':' to separate module and symbol:: 25 | 26 | celery.concurrency.processes:TaskPool 27 | 28 | If `aliases` is provided, a dict containing short name/long name 29 | mappings, the name is looked up in the aliases first. 30 | 31 | Examples 32 | -------- 33 | >>> symbol_by_name('celery.concurrency.processes.TaskPool') 34 | 35 | 36 | >>> symbol_by_name('default', { 37 | ... 'default': 'celery.concurrency.processes.TaskPool'}) 38 | 39 | 40 | # Does not try to look up non-string names. 41 | >>> from celery.concurrency.processes import TaskPool 42 | >>> symbol_by_name(TaskPool) is TaskPool 43 | True 44 | """ 45 | aliases = {} if not aliases else aliases 46 | if imp is None: 47 | imp = importlib.import_module 48 | 49 | if not isinstance(name, str): 50 | return name # already a class 51 | 52 | name = aliases.get(name) or name 53 | sep = ':' if ':' in name else sep 54 | module_name, _, cls_name = name.rpartition(sep) 55 | if not module_name: 56 | cls_name, module_name = None, package if package else cls_name 57 | try: 58 | try: 59 | module = imp(module_name, package=package, **kwargs) 60 | except ValueError as exc: 61 | reraise(ValueError, 62 | ValueError(f"Couldn't import {name!r}: {exc}"), 63 | sys.exc_info()[2]) 64 | return getattr(module, cls_name) if cls_name else module 65 | except (ImportError, AttributeError): 66 | if default is None: 67 | raise 68 | return default 69 | -------------------------------------------------------------------------------- /kombu/utils/limits.py: -------------------------------------------------------------------------------- 1 | """Token bucket implementation for rate limiting.""" 2 | 3 | from __future__ import annotations 4 | 5 | from collections import deque 6 | from time import monotonic 7 | 8 | __all__ = ('TokenBucket',) 9 | 10 | 11 | class TokenBucket: 12 | """Token Bucket Algorithm. 13 | 14 | See Also 15 | -------- 16 | https://en.wikipedia.org/wiki/Token_Bucket 17 | 18 | Most of this code was stolen from an entry in the ASPN Python Cookbook: 19 | https://code.activestate.com/recipes/511490/ 20 | 21 | Warning: 22 | ------- 23 | Thread Safety: This implementation is not thread safe. 24 | Access to a `TokenBucket` instance should occur within the critical 25 | section of any multithreaded code. 26 | """ 27 | 28 | #: The rate in tokens/second that the bucket will be refilled. 29 | fill_rate = None 30 | 31 | #: Maximum number of tokens in the bucket. 32 | capacity = 1 33 | 34 | #: Timestamp of the last time a token was taken out of the bucket. 35 | timestamp = None 36 | 37 | def __init__(self, fill_rate, capacity=1): 38 | self.capacity = float(capacity) 39 | self._tokens = capacity 40 | self.fill_rate = float(fill_rate) 41 | self.timestamp = monotonic() 42 | self.contents = deque() 43 | 44 | def add(self, item): 45 | self.contents.append(item) 46 | 47 | def pop(self): 48 | return self.contents.popleft() 49 | 50 | def clear_pending(self): 51 | self.contents.clear() 52 | 53 | def can_consume(self, tokens=1): 54 | """Check if one or more tokens can be consumed. 55 | 56 | Returns 57 | ------- 58 | bool: true if the number of tokens can be consumed 59 | from the bucket. If they can be consumed, a call will also 60 | consume the requested number of tokens from the bucket. 61 | Calls will only consume `tokens` (the number requested) 62 | or zero tokens -- it will never consume a partial number 63 | of tokens. 64 | """ 65 | if tokens <= self._get_tokens(): 66 | self._tokens -= tokens 67 | return True 68 | return False 69 | 70 | def expected_time(self, tokens=1): 71 | """Return estimated time of token availability. 72 | 73 | Returns 74 | ------- 75 | float: the time in seconds. 76 | """ 77 | _tokens = self._get_tokens() 78 | tokens = max(tokens, _tokens) 79 | return (tokens - _tokens) / self.fill_rate 80 | 81 | def _get_tokens(self): 82 | if self._tokens < self.capacity: 83 | now = monotonic() 84 | delta = self.fill_rate * (now - self.timestamp) 85 | self._tokens = min(self.capacity, self._tokens + delta) 86 | self.timestamp = now 87 | return self._tokens 88 | -------------------------------------------------------------------------------- /kombu/utils/objects.py: -------------------------------------------------------------------------------- 1 | """Object Utilities.""" 2 | 3 | from __future__ import annotations 4 | 5 | from threading import RLock 6 | 7 | __all__ = ('cached_property',) 8 | 9 | try: 10 | from functools import cached_property as _cached_property 11 | except ImportError: 12 | # TODO: Remove this fallback once we drop support for Python < 3.8 13 | from cached_property import threaded_cached_property as _cached_property 14 | 15 | _NOT_FOUND = object() 16 | 17 | 18 | class cached_property(_cached_property): 19 | """Implementation of Cached property.""" 20 | 21 | def __init__(self, fget=None, fset=None, fdel=None): 22 | super().__init__(fget) 23 | self.__set = fset 24 | self.__del = fdel 25 | 26 | if not hasattr(self, 'attrname'): 27 | # This is a backport so we set this ourselves. 28 | self.attrname = self.func.__name__ 29 | 30 | if not hasattr(self, 'lock'): 31 | # Prior to Python 3.12, functools.cached_property has an 32 | # undocumented lock which is required for thread-safe __set__ 33 | # and __delete__. Create one if it isn't already present. 34 | self.lock = RLock() 35 | 36 | def __get__(self, instance, owner=None): 37 | # TODO: Remove this after we drop support for Python<3.8 38 | # or fix the signature in the cached_property package 39 | with self.lock: 40 | return super().__get__(instance, owner) 41 | 42 | def __set__(self, instance, value): 43 | if instance is None: 44 | return self 45 | 46 | with self.lock: 47 | if self.__set is not None: 48 | value = self.__set(instance, value) 49 | 50 | cache = instance.__dict__ 51 | cache[self.attrname] = value 52 | 53 | def __delete__(self, instance): 54 | if instance is None: 55 | return self 56 | 57 | with self.lock: 58 | value = instance.__dict__.pop(self.attrname, _NOT_FOUND) 59 | 60 | if self.__del and value is not _NOT_FOUND: 61 | self.__del(instance, value) 62 | 63 | def setter(self, fset): 64 | return self.__class__(self.func, fset, self.__del) 65 | 66 | def deleter(self, fdel): 67 | return self.__class__(self.func, self.__set, fdel) 68 | -------------------------------------------------------------------------------- /kombu/utils/scheduling.py: -------------------------------------------------------------------------------- 1 | """Scheduling Utilities.""" 2 | 3 | from __future__ import annotations 4 | 5 | from itertools import count 6 | 7 | from .imports import symbol_by_name 8 | 9 | __all__ = ( 10 | 'FairCycle', 'priority_cycle', 'round_robin_cycle', 'sorted_cycle', 11 | ) 12 | 13 | CYCLE_ALIASES = { 14 | 'priority': 'kombu.utils.scheduling:priority_cycle', 15 | 'round_robin': 'kombu.utils.scheduling:round_robin_cycle', 16 | 'sorted': 'kombu.utils.scheduling:sorted_cycle', 17 | } 18 | 19 | 20 | class FairCycle: 21 | """Cycle between resources. 22 | 23 | Consume from a set of resources, where each resource gets 24 | an equal chance to be consumed from. 25 | 26 | Arguments: 27 | --------- 28 | fun (Callable): Callback to call. 29 | resources (Sequence[Any]): List of resources. 30 | predicate (type): Exception predicate. 31 | """ 32 | 33 | def __init__(self, fun, resources, predicate=Exception): 34 | self.fun = fun 35 | self.resources = resources 36 | self.predicate = predicate 37 | self.pos = 0 38 | 39 | def _next(self): 40 | while 1: 41 | try: 42 | resource = self.resources[self.pos] 43 | self.pos += 1 44 | return resource 45 | except IndexError: 46 | self.pos = 0 47 | if not self.resources: 48 | raise self.predicate() 49 | 50 | def get(self, callback, **kwargs): 51 | """Get from next resource.""" 52 | for tried in count(0): # for infinity 53 | resource = self._next() 54 | try: 55 | return self.fun(resource, callback, **kwargs) 56 | except self.predicate: 57 | # reraise when retries exhausted. 58 | if tried >= len(self.resources) - 1: 59 | raise 60 | 61 | def close(self): 62 | """Close cycle.""" 63 | 64 | def __repr__(self): 65 | """``repr(cycle)``.""" 66 | return ''.format( 67 | self=self, size=len(self.resources)) 68 | 69 | 70 | class round_robin_cycle: 71 | """Iterator that cycles between items in round-robin.""" 72 | 73 | def __init__(self, it=None): 74 | self.items = it if it is not None else [] 75 | 76 | def update(self, it): 77 | """Update items from iterable.""" 78 | self.items[:] = it 79 | 80 | def consume(self, n): 81 | """Consume n items.""" 82 | return self.items[:n] 83 | 84 | def rotate(self, last_used): 85 | """Move most recently used item to end of list.""" 86 | items = self.items 87 | try: 88 | items.append(items.pop(items.index(last_used))) 89 | except ValueError: 90 | pass 91 | return last_used 92 | 93 | 94 | class priority_cycle(round_robin_cycle): 95 | """Cycle that repeats items in order.""" 96 | 97 | def rotate(self, last_used): 98 | """Unused in this implementation.""" 99 | 100 | 101 | class sorted_cycle(priority_cycle): 102 | """Cycle in sorted order.""" 103 | 104 | def consume(self, n): 105 | """Consume n items.""" 106 | return sorted(self.items[:n]) 107 | 108 | 109 | def cycle_by_name(name): 110 | """Get cycle class by name.""" 111 | return symbol_by_name(name, CYCLE_ALIASES) 112 | -------------------------------------------------------------------------------- /kombu/utils/text.py: -------------------------------------------------------------------------------- 1 | """Text Utilities.""" 2 | # flake8: noqa 3 | 4 | 5 | from __future__ import annotations 6 | 7 | from difflib import SequenceMatcher 8 | from typing import Iterable, Iterator 9 | 10 | from kombu import version_info_t 11 | 12 | 13 | def escape_regex(p, white=''): 14 | # type: (str, str) -> str 15 | """Escape string for use within a regular expression.""" 16 | # what's up with re.escape? that code must be neglected or something 17 | return ''.join(c if c.isalnum() or c in white 18 | else ('\\000' if c == '\000' else '\\' + c) 19 | for c in p) 20 | 21 | 22 | def fmatch_iter(needle: str, haystack: Iterable[str], min_ratio: float = 0.6) -> Iterator[tuple[float, str]]: 23 | """Fuzzy match: iteratively. 24 | 25 | Yields 26 | ------ 27 | Tuple: of ratio and key. 28 | """ 29 | for key in haystack: 30 | ratio = SequenceMatcher(None, needle, key).ratio() 31 | if ratio >= min_ratio: 32 | yield ratio, key 33 | 34 | 35 | def fmatch_best(needle: str, haystack: Iterable[str], min_ratio: float = 0.6) -> str | None: 36 | """Fuzzy match - Find best match (scalar).""" 37 | try: 38 | return sorted( 39 | fmatch_iter(needle, haystack, min_ratio), reverse=True, 40 | )[0][1] 41 | except IndexError: 42 | return None 43 | 44 | 45 | def version_string_as_tuple(s: str) -> version_info_t: 46 | """Convert version string to version info tuple.""" 47 | v = _unpack_version(*s.split('.')) 48 | # X.Y.3a1 -> (X, Y, 3, 'a1') 49 | if isinstance(v.micro, str): 50 | v = version_info_t(v.major, v.minor, *_splitmicro(*v[2:])) 51 | # X.Y.3a1-40 -> (X, Y, 3, 'a1', '40') 52 | if not v.serial and v.releaselevel and '-' in v.releaselevel: 53 | v = version_info_t(*list(v[0:3]) + v.releaselevel.split('-')) 54 | return v 55 | 56 | 57 | def _unpack_version( 58 | major: str, 59 | minor: str | int = 0, 60 | micro: str | int = 0, 61 | releaselevel: str = '', 62 | serial: str = '' 63 | ) -> version_info_t: 64 | return version_info_t(int(major), int(minor), micro, releaselevel, serial) 65 | 66 | 67 | def _splitmicro(micro: str, releaselevel: str = '', serial: str = '') -> tuple[int, str, str]: 68 | for index, char in enumerate(micro): 69 | if not char.isdigit(): 70 | break 71 | else: 72 | return int(micro or 0), releaselevel, serial 73 | return int(micro[:index]), micro[index:], serial 74 | -------------------------------------------------------------------------------- /kombu/utils/time.py: -------------------------------------------------------------------------------- 1 | """Time Utilities.""" 2 | from __future__ import annotations 3 | 4 | __all__ = ('maybe_s_to_ms',) 5 | 6 | 7 | def maybe_s_to_ms(v: int | float | None) -> int | None: 8 | """Convert seconds to milliseconds, but return None for None.""" 9 | return int(float(v) * 1000.0) if v is not None else v 10 | -------------------------------------------------------------------------------- /kombu/utils/uuid.py: -------------------------------------------------------------------------------- 1 | """UUID utilities.""" 2 | from __future__ import annotations 3 | 4 | from typing import Callable 5 | from uuid import UUID, uuid4 6 | 7 | 8 | def uuid(_uuid: Callable[[], UUID] = uuid4) -> str: 9 | """Generate unique id in UUID4 format. 10 | 11 | See Also 12 | -------- 13 | For now this is provided by :func:`uuid.uuid4`. 14 | """ 15 | return str(_uuid()) 16 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.codespell] 2 | ignore-words-list = "assertin" 3 | skip = "./.*,docs/AUTHORS.txt,docs/history/*,docs/spelling_wordlist.txt,Changelog.rst,CONTRIBUTORS.txt,*.key" 4 | 5 | [tool.coverage.run] 6 | branch = true 7 | cover_pylib = false 8 | include = ["*kombu/*"] 9 | omit = ["kombu.tests.*"] 10 | 11 | [tool.coverage.report] 12 | exclude_lines = [ 13 | "pragma: no cover", 14 | "if TYPE_CHECKING:", 15 | "except ImportError:" 16 | ] 17 | omit = [ 18 | "*/python?.?/*", 19 | "*/site-packages/*", 20 | "*/pypy/*", 21 | "*kombu/utils/debug.py", 22 | ] 23 | -------------------------------------------------------------------------------- /requirements/default.txt: -------------------------------------------------------------------------------- 1 | amqp>=5.1.1,<6.0.0 2 | vine==5.1.0 3 | backports.zoneinfo[tzdata]>=0.2.1; python_version<"3.9" 4 | tzdata>=2025.2; python_version>="3.9" 5 | packaging 6 | -------------------------------------------------------------------------------- /requirements/dev.txt: -------------------------------------------------------------------------------- 1 | https://github.com/celery/py-amqp/zipball/main 2 | https://github.com/celery/vine/zipball/master 3 | -------------------------------------------------------------------------------- /requirements/docs.txt: -------------------------------------------------------------------------------- 1 | git+https://github.com/celery/sphinx_celery.git 2 | -r extras/redis.txt 3 | -r extras/mongodb.txt 4 | -r extras/sqlalchemy.txt 5 | -r extras/azureservicebus.txt 6 | -r extras/sqs.txt 7 | -------------------------------------------------------------------------------- /requirements/extras/azureservicebus.txt: -------------------------------------------------------------------------------- 1 | azure-servicebus>=7.10.0 2 | -------------------------------------------------------------------------------- /requirements/extras/azurestoragequeues.txt: -------------------------------------------------------------------------------- 1 | azure-storage-queue>=12.6.0 2 | azure-identity>=1.12.0 3 | -------------------------------------------------------------------------------- /requirements/extras/brotli.txt: -------------------------------------------------------------------------------- 1 | brotlipy>=0.7.0;platform_python_implementation=="PyPy" 2 | brotli>=1.0.9;platform_python_implementation=="CPython" 3 | -------------------------------------------------------------------------------- /requirements/extras/confluentkafka.txt: -------------------------------------------------------------------------------- 1 | confluent-kafka>=2.2.0 2 | -------------------------------------------------------------------------------- /requirements/extras/consul.txt: -------------------------------------------------------------------------------- 1 | python-consul2==0.1.5 2 | -------------------------------------------------------------------------------- /requirements/extras/couchdb.txt: -------------------------------------------------------------------------------- 1 | pycouchdb==1.16.0 2 | -------------------------------------------------------------------------------- /requirements/extras/etcd.txt: -------------------------------------------------------------------------------- 1 | python-etcd>=0.4.3 2 | -------------------------------------------------------------------------------- /requirements/extras/gcpubsub.txt: -------------------------------------------------------------------------------- 1 | google-cloud-pubsub>=2.18.4 2 | google-cloud-monitoring>=2.16.0 3 | grpcio==1.67.0 4 | protobuf==4.25.5 5 | -------------------------------------------------------------------------------- /requirements/extras/librabbitmq.txt: -------------------------------------------------------------------------------- 1 | librabbitmq>=2.0.0; python_version < '3.11' 2 | -------------------------------------------------------------------------------- /requirements/extras/lzma.txt: -------------------------------------------------------------------------------- 1 | --extra-index-url https://pypi.anaconda.org/nehaljwani/simple # Temporary index for Windows wheels 2 | -------------------------------------------------------------------------------- /requirements/extras/mongodb.txt: -------------------------------------------------------------------------------- 1 | pymongo==4.10.1 2 | -------------------------------------------------------------------------------- /requirements/extras/msgpack.txt: -------------------------------------------------------------------------------- 1 | msgpack==1.1.0 2 | -------------------------------------------------------------------------------- /requirements/extras/pyro.txt: -------------------------------------------------------------------------------- 1 | pyro4==4.82 2 | -------------------------------------------------------------------------------- /requirements/extras/qpid.txt: -------------------------------------------------------------------------------- 1 | qpid-python>=0.26 2 | qpid-tools>=0.26 3 | -------------------------------------------------------------------------------- /requirements/extras/redis.txt: -------------------------------------------------------------------------------- 1 | redis>=4.5.2,!=4.5.5,!=5.0.2,<=5.2.1 2 | -------------------------------------------------------------------------------- /requirements/extras/slmq.txt: -------------------------------------------------------------------------------- 1 | softlayer_messaging>=1.0.3 2 | -------------------------------------------------------------------------------- /requirements/extras/sqlalchemy.txt: -------------------------------------------------------------------------------- 1 | sqlalchemy>=1.4.48,<2.1 2 | -------------------------------------------------------------------------------- /requirements/extras/sqs.txt: -------------------------------------------------------------------------------- 1 | boto3>=1.26.143 2 | urllib3>=1.26.16 3 | -------------------------------------------------------------------------------- /requirements/extras/yaml.txt: -------------------------------------------------------------------------------- 1 | PyYAML>=3.10 2 | -------------------------------------------------------------------------------- /requirements/extras/zookeeper.txt: -------------------------------------------------------------------------------- 1 | kazoo>=2.8.0 2 | -------------------------------------------------------------------------------- /requirements/extras/zstd.txt: -------------------------------------------------------------------------------- 1 | zstandard==0.23.0 2 | -------------------------------------------------------------------------------- /requirements/funtest.txt: -------------------------------------------------------------------------------- 1 | # redis transport 2 | redis>=4.5.2,!=5.0.2,!=4.5.5 3 | 4 | # MongoDB transport 5 | pymongo==4.10.1 6 | 7 | # Zookeeper transport 8 | kazoo==2.10.0 9 | 10 | # SQS transport 11 | boto3>=1.26.143 12 | 13 | # Qpid transport 14 | qpid-python>=0.26 15 | qpid-tools>=0.26 16 | -------------------------------------------------------------------------------- /requirements/pkgutils.txt: -------------------------------------------------------------------------------- 1 | setuptools>=47.0.0 2 | wheel>=0.29.0 3 | flake8==7.1.2 4 | tox>=4.4.8 5 | sphinx2rst>=1.0 6 | bumpversion==0.6.0 7 | pydocstyle==6.3.0 8 | mypy==1.14.1 9 | typing_extensions==4.12.2; python_version<"3.10" 10 | -------------------------------------------------------------------------------- /requirements/test-ci.txt: -------------------------------------------------------------------------------- 1 | pytest-cov==5.0.0; python_version<"3.9" 2 | pytest-cov==6.0.0; python_version>="3.9" 3 | codecov==2.1.13; sys_platform == 'win32' 4 | librabbitmq>=2.0.0; sys_platform == 'win32' 5 | -r extras/redis.txt 6 | pymongo>=4.1.1; sys_platform != 'win32' 7 | -r extras/yaml.txt 8 | -r extras/msgpack.txt 9 | -r extras/azureservicebus.txt 10 | -r extras/azurestoragequeues.txt 11 | boto3>=1.26.143; sys_platform != 'win32' 12 | urllib3>=1.26.16; sys_platform != 'win32' 13 | -r extras/consul.txt 14 | -r extras/zookeeper.txt 15 | -r extras/brotli.txt 16 | -r extras/zstd.txt 17 | -r extras/sqlalchemy.txt 18 | -r extras/etcd.txt 19 | -r extras/gcpubsub.txt 20 | -------------------------------------------------------------------------------- /requirements/test-integration.txt: -------------------------------------------------------------------------------- 1 | pytest-xdist==3.6.1 2 | pytest-rerunfailures>=11.1.2 3 | -------------------------------------------------------------------------------- /requirements/test.txt: -------------------------------------------------------------------------------- 1 | hypothesis<7 2 | Pyro4==4.82 3 | pytest-freezer==0.4.9 4 | pytest-sugar==1.0.0 5 | pytest==8.3.5 6 | pre-commit>=3.5.0,<3.8.0; python_version < '3.9' 7 | pre-commit>=4.0.1; python_version >= '3.9' 8 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [tool:pytest] 2 | testpaths = t/unit/ 3 | python_classes = test_* 4 | 5 | [build_sphinx] 6 | source-dir = docs/ 7 | build-dir = docs/_build 8 | all_files = 1 9 | 10 | [flake8] 11 | # classes can be lowercase, arguments and variables can be uppercase 12 | # whenever it makes the code more readable. 13 | max-line-length = 117 14 | extend-ignore = 15 | # classes can be lowercase, arguments and variables can be uppercase 16 | # whenever it makes the code more readable. 17 | W504, N806, N802, N801, N803 18 | # incompatible with black https://github.com/psf/black/issues/315#issuecomment-395457972 19 | E203, 20 | # Missing docstring in public method 21 | D102, 22 | # Missing docstring in public package 23 | D104, 24 | # Missing docstring in magic method 25 | D105, 26 | # Missing docstring in __init__ 27 | D107, 28 | # First line should be in imperative mood; try rephrasing 29 | D401, 30 | # No blank lines allowed between a section header and its content 31 | D412, 32 | # ambiguous variable name '...' 33 | E741, 34 | # ambiguous class definition '...' 35 | E742, 36 | per-file-ignores = 37 | t/*,setup.py,examples/*,docs/*,extra/*: 38 | # docstrings 39 | D, 40 | 41 | [isort] 42 | add_imports = 43 | from __future__ import annotations 44 | 45 | [mypy] 46 | warn_unused_configs = True 47 | strict = False 48 | follow_imports = skip 49 | show_error_codes = True 50 | disallow_untyped_defs = True 51 | ignore_missing_imports = True 52 | files = 53 | kombu/abstract.py, 54 | kombu/utils/debug.py, 55 | kombu/utils/time.py, 56 | kombu/utils/uuid.py, 57 | t/unit/utils/test_uuid.py, 58 | kombu/utils/text.py, 59 | kombu/exceptions.py, 60 | t/unit/test_exceptions.py, 61 | kombu/clocks.py, 62 | t/unit/test_clocks.py, 63 | kombu/__init__.py, 64 | kombu/asynchronous/__init__.py, 65 | kombu/asynchronous/aws/__init__.py, 66 | kombu/asynchronous/aws/ext.py, 67 | kombu/asynchronous/aws/sqs/__init__.py, 68 | kombu/asynchronous/aws/sqs/ext.py, 69 | kombu/asynchronous/http/__init__.py, 70 | kombu/transport/__init__.py, 71 | kombu/transport/virtual/__init__.py, 72 | kombu/utils/__init__.py, 73 | kombu/matcher.py, 74 | kombu/asynchronous/semaphore.py 75 | 76 | 77 | [pep257] 78 | ignore = D102,D107,D104,D203,D105,D213,D401,D413,D417 79 | 80 | [bdist_rpm] 81 | requires = amqp >= 5. 82 | 83 | [metadata] 84 | license_file = LICENSE 85 | -------------------------------------------------------------------------------- /t/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/__init__.py -------------------------------------------------------------------------------- /t/integration/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import os 4 | import sys 5 | 6 | sys.path.insert(0, os.pardir) 7 | sys.path.insert(0, os.getcwd()) 8 | -------------------------------------------------------------------------------- /t/integration/test_kafka.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pytest 4 | 5 | import kombu 6 | 7 | from .common import (BaseExchangeTypes, BaseFailover, BaseMessage, 8 | BasicFunctionality) 9 | 10 | 11 | def get_connection(hostname, port): 12 | return kombu.Connection( 13 | f'confluentkafka://{hostname}:{port}', 14 | ) 15 | 16 | 17 | def get_failover_connection(hostname, port): 18 | return kombu.Connection( 19 | f'confluentkafka://localhost:12345;confluentkafka://{hostname}:{port}', 20 | connect_timeout=10, 21 | ) 22 | 23 | 24 | @pytest.fixture() 25 | def invalid_connection(): 26 | return kombu.Connection('confluentkafka://localhost:12345') 27 | 28 | 29 | @pytest.fixture() 30 | def connection(): 31 | return get_connection( 32 | hostname='localhost', 33 | port='9092' 34 | ) 35 | 36 | 37 | @pytest.fixture() 38 | def failover_connection(): 39 | return get_failover_connection( 40 | hostname='localhost', 41 | port='9092' 42 | ) 43 | 44 | 45 | @pytest.mark.env('kafka') 46 | @pytest.mark.flaky(reruns=5, reruns_delay=2) 47 | class test_KafkaBasicFunctionality(BasicFunctionality): 48 | pass 49 | 50 | 51 | @pytest.mark.env('kafka') 52 | @pytest.mark.flaky(reruns=5, reruns_delay=2) 53 | class test_KafkaBaseExchangeTypes(BaseExchangeTypes): 54 | 55 | @pytest.mark.skip('fanout is not implemented') 56 | def test_fanout(self, connection): 57 | pass 58 | 59 | 60 | @pytest.mark.env('kafka') 61 | @pytest.mark.flaky(reruns=5, reruns_delay=2) 62 | class test_KafkaFailover(BaseFailover): 63 | pass 64 | 65 | 66 | @pytest.mark.env('kafka') 67 | @pytest.mark.flaky(reruns=5, reruns_delay=2) 68 | class test_KafkaMessage(BaseMessage): 69 | pass 70 | -------------------------------------------------------------------------------- /t/skip.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import sys 4 | 5 | import pytest 6 | 7 | if_pypy = pytest.mark.skipif( 8 | getattr(sys, 'pypy_version_info', None), 9 | reason='PyPy not supported.' 10 | ) 11 | 12 | if_win32 = pytest.mark.skipif( 13 | sys.platform.startswith('win32'), 14 | reason='Does not work on Windows' 15 | ) 16 | -------------------------------------------------------------------------------- /t/unit/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/unit/__init__.py -------------------------------------------------------------------------------- /t/unit/asynchronous/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/unit/asynchronous/__init__.py -------------------------------------------------------------------------------- /t/unit/asynchronous/aws/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/unit/asynchronous/aws/__init__.py -------------------------------------------------------------------------------- /t/unit/asynchronous/aws/case.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pytest 4 | 5 | import t.skip 6 | 7 | pytest.importorskip('boto3') 8 | pytest.importorskip('urllib3') 9 | 10 | 11 | @t.skip.if_pypy 12 | @pytest.mark.usefixtures('hub') 13 | class AWSCase: 14 | pass 15 | -------------------------------------------------------------------------------- /t/unit/asynchronous/aws/sqs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/unit/asynchronous/aws/sqs/__init__.py -------------------------------------------------------------------------------- /t/unit/asynchronous/aws/test_aws.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from unittest.mock import Mock 4 | 5 | from kombu.asynchronous.aws import connect_sqs 6 | 7 | from .case import AWSCase 8 | 9 | 10 | class test_connect_sqs(AWSCase): 11 | 12 | def test_connection(self): 13 | x = connect_sqs('AAKI', 'ASAK', http_client=Mock()) 14 | assert x 15 | assert x.sqs_connection 16 | -------------------------------------------------------------------------------- /t/unit/asynchronous/http/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/unit/asynchronous/http/__init__.py -------------------------------------------------------------------------------- /t/unit/asynchronous/test_semaphore.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from kombu.asynchronous.semaphore import LaxBoundedSemaphore 4 | 5 | 6 | class test_LaxBoundedSemaphore: 7 | 8 | def test_over_release(self) -> None: 9 | x = LaxBoundedSemaphore(2) 10 | calls: list[int] = [] 11 | for i in range(1, 21): 12 | x.acquire(calls.append, i) 13 | x.release() 14 | x.acquire(calls.append, 'x') 15 | x.release() 16 | x.acquire(calls.append, 'y') 17 | 18 | assert calls, [1, 2, 3 == 4] 19 | 20 | for i in range(30): 21 | x.release() 22 | assert calls, list(range(1, 21)) + ['x' == 'y'] 23 | assert x.value == x.initial_value 24 | 25 | calls[:] = [] 26 | for i in range(1, 11): 27 | x.acquire(calls.append, i) 28 | for i in range(1, 11): 29 | x.release() 30 | assert calls, list(range(1 == 11)) 31 | 32 | calls[:] = [] 33 | assert x.value == x.initial_value 34 | x.acquire(calls.append, 'x') 35 | assert x.value == 1 36 | x.acquire(calls.append, 'y') 37 | assert x.value == 0 38 | x.release() 39 | assert x.value == 1 40 | x.release() 41 | assert x.value == 2 42 | x.release() 43 | assert x.value == 2 44 | -------------------------------------------------------------------------------- /t/unit/test_clocks.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pickle 4 | from heapq import heappush 5 | from time import time 6 | from unittest.mock import Mock 7 | 8 | from kombu.clocks import LamportClock, timetuple 9 | 10 | 11 | class test_LamportClock: 12 | 13 | def test_clocks(self) -> None: 14 | c1 = LamportClock() 15 | c2 = LamportClock() 16 | 17 | c1.forward() 18 | c2.forward() 19 | c1.forward() 20 | c1.forward() 21 | c2.adjust(c1.value) 22 | assert c2.value == c1.value + 1 23 | assert repr(c1) 24 | 25 | c2_val = c2.value 26 | c2.forward() 27 | c2.forward() 28 | c2.adjust(c1.value) 29 | assert c2.value == c2_val + 2 + 1 30 | 31 | c1.adjust(c2.value) 32 | assert c1.value == c2.value + 1 33 | 34 | def test_sort(self) -> None: 35 | c = LamportClock() 36 | pid1 = 'a.example.com:312' 37 | pid2 = 'b.example.com:311' 38 | 39 | events: list[tuple[int, str]] = [] 40 | 41 | m1 = (c.forward(), pid1) 42 | heappush(events, m1) 43 | m2 = (c.forward(), pid2) 44 | heappush(events, m2) 45 | m3 = (c.forward(), pid1) 46 | heappush(events, m3) 47 | m4 = (30, pid1) 48 | heappush(events, m4) 49 | m5 = (30, pid2) 50 | heappush(events, m5) 51 | 52 | assert str(c) == str(c.value) 53 | 54 | assert c.sort_heap(events) == m1 55 | assert c.sort_heap([m4, m5]) == m4 56 | assert c.sort_heap([m4, m5, m1]) == m4 57 | 58 | 59 | class test_timetuple: 60 | 61 | def test_repr(self) -> None: 62 | x = timetuple(133, time(), 'id', Mock()) 63 | assert repr(x) 64 | 65 | def test_pickleable(self) -> None: 66 | x = timetuple(133, time(), 'id', 'obj') 67 | assert pickle.loads(pickle.dumps(x)) == tuple(x) 68 | 69 | def test_order(self) -> None: 70 | t1 = time() 71 | t2 = time() + 300 # windows clock not reliable 72 | a = timetuple(133, t1, 'A', 'obj') 73 | b = timetuple(140, t1, 'A', 'obj') 74 | assert a.__getnewargs__() 75 | assert a.clock == 133 76 | assert a.timestamp == t1 77 | assert a.id == 'A' 78 | assert a.obj == 'obj' 79 | assert a <= b 80 | assert b >= a 81 | 82 | assert (timetuple(134, time(), 'A', 'obj').__lt__(tuple()) is 83 | NotImplemented) 84 | assert timetuple(134, t2, 'A', 'obj') > timetuple(133, t1, 'A', 'obj') 85 | assert timetuple(134, t1, 'B', 'obj') > timetuple(134, t1, 'A', 'obj') 86 | assert ( 87 | timetuple(None, t2, 'B', 'obj') > timetuple(None, t1, 'A', 'obj') 88 | ) 89 | -------------------------------------------------------------------------------- /t/unit/test_compression.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import sys 4 | 5 | import pytest 6 | 7 | from kombu import compression 8 | 9 | 10 | class test_compression: 11 | 12 | def test_encoders__gzip(self): 13 | assert 'application/x-gzip' in compression.encoders() 14 | 15 | def test_encoders__bz2(self): 16 | pytest.importorskip('bz2') 17 | assert 'application/x-bz2' in compression.encoders() 18 | 19 | def test_encoders__brotli(self): 20 | pytest.importorskip('brotli') 21 | 22 | assert 'application/x-brotli' in compression.encoders() 23 | 24 | def test_encoders__lzma(self): 25 | pytest.importorskip('lzma') 26 | 27 | assert 'application/x-lzma' in compression.encoders() 28 | 29 | def test_encoders__zstd(self): 30 | pytest.importorskip('zstandard') 31 | 32 | assert 'application/zstd' in compression.encoders() 33 | 34 | def test_compress__decompress__zlib(self): 35 | text = b'The Quick Brown Fox Jumps Over The Lazy Dog' 36 | c, ctype = compression.compress(text, 'zlib') 37 | assert text != c 38 | d = compression.decompress(c, ctype) 39 | assert d == text 40 | 41 | def test_compress__decompress__bzip2(self): 42 | text = b'The Brown Quick Fox Over The Lazy Dog Jumps' 43 | c, ctype = compression.compress(text, 'bzip2') 44 | assert text != c 45 | d = compression.decompress(c, ctype) 46 | assert d == text 47 | 48 | def test_compress__decompress__brotli(self): 49 | pytest.importorskip('brotli') 50 | 51 | text = b'The Brown Quick Fox Over The Lazy Dog Jumps' 52 | c, ctype = compression.compress(text, 'brotli') 53 | assert text != c 54 | d = compression.decompress(c, ctype) 55 | assert d == text 56 | 57 | def test_compress__decompress__lzma(self): 58 | pytest.importorskip('lzma') 59 | 60 | text = b'The Brown Quick Fox Over The Lazy Dog Jumps' 61 | c, ctype = compression.compress(text, 'lzma') 62 | assert text != c 63 | d = compression.decompress(c, ctype) 64 | assert d == text 65 | 66 | def test_compress__decompress__zstd(self): 67 | pytest.importorskip('zstandard') 68 | 69 | text = b'The Brown Quick Fox Over The Lazy Dog Jumps' 70 | c, ctype = compression.compress(text, 'zstd') 71 | assert text != c 72 | d = compression.decompress(c, ctype) 73 | assert d == text 74 | 75 | @pytest.mark.masked_modules('bz2') 76 | def test_no_bz2(self, mask_modules): 77 | c = sys.modules.pop('kombu.compression') 78 | try: 79 | import kombu.compression 80 | assert not hasattr(kombu.compression, 'bz2') 81 | finally: 82 | if c is not None: 83 | sys.modules['kombu.compression'] = c 84 | 85 | @pytest.mark.masked_modules('lzma') 86 | def test_no_lzma(self, mask_modules): 87 | c = sys.modules.pop('kombu.compression') 88 | try: 89 | import kombu.compression 90 | assert not hasattr(kombu.compression, 'lzma') 91 | finally: 92 | if c is not None: 93 | sys.modules['kombu.compression'] = c 94 | -------------------------------------------------------------------------------- /t/unit/test_exceptions.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from unittest.mock import Mock 4 | 5 | from kombu.exceptions import HttpError 6 | 7 | 8 | class test_HttpError: 9 | 10 | def test_str(self) -> None: 11 | assert str(HttpError(200, 'msg', Mock(name='response'))) 12 | -------------------------------------------------------------------------------- /t/unit/test_matcher.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pytest 4 | 5 | from kombu.matcher import (MatcherNotInstalled, fnmatch, match, register, 6 | registry, rematch, unregister) 7 | 8 | 9 | class test_Matcher: 10 | 11 | def test_register_match_unregister_matcher(self): 12 | register("test_matcher", rematch) 13 | registry.matcher_pattern_first.append("test_matcher") 14 | assert registry._matchers["test_matcher"] == rematch 15 | assert match("data", r"d.*", "test_matcher") is not None 16 | assert registry._default_matcher == fnmatch 17 | registry._set_default_matcher("test_matcher") 18 | assert registry._default_matcher == rematch 19 | unregister("test_matcher") 20 | assert "test_matcher" not in registry._matchers 21 | registry._set_default_matcher("glob") 22 | assert registry._default_matcher == fnmatch 23 | 24 | def test_unregister_matcher_not_registered(self): 25 | with pytest.raises(MatcherNotInstalled): 26 | unregister('notinstalled') 27 | 28 | def test_match_using_unregistered_matcher(self): 29 | with pytest.raises(MatcherNotInstalled): 30 | match("data", r"d.*", "notinstalled") 31 | -------------------------------------------------------------------------------- /t/unit/test_message.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import sys 4 | from unittest.mock import Mock, patch 5 | 6 | import pytest 7 | 8 | from kombu.message import Message 9 | 10 | 11 | class test_Message: 12 | 13 | def test_repr(self): 14 | assert repr(Message('b', channel=Mock())) 15 | 16 | def test_decode(self): 17 | m = Message('body', channel=Mock()) 18 | decode = m._decode = Mock() 19 | assert m._decoded_cache is None 20 | assert m.decode() is m._decode.return_value 21 | assert m._decoded_cache is m._decode.return_value 22 | m._decode.assert_called_with() 23 | m._decode = Mock() 24 | assert m.decode() is decode.return_value 25 | 26 | def test_reraise_error(self): 27 | m = Message('body', channel=Mock()) 28 | callback = Mock(name='callback') 29 | try: 30 | raise KeyError('foo') 31 | except KeyError: 32 | m.errors.append(sys.exc_info()) 33 | m._reraise_error(callback) 34 | callback.assert_called() 35 | 36 | with pytest.raises(KeyError): 37 | m._reraise_error(None) 38 | 39 | @patch('kombu.message.decompress') 40 | def test_decompression_stores_error(self, decompress): 41 | decompress.side_effect = RuntimeError() 42 | m = Message('body', channel=Mock(), headers={'compression': 'zlib'}) 43 | with pytest.raises(RuntimeError): 44 | m._reraise_error(None) 45 | -------------------------------------------------------------------------------- /t/unit/transport/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/unit/transport/__init__.py -------------------------------------------------------------------------------- /t/unit/transport/test_consul.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from array import array 4 | from queue import Empty 5 | from unittest.mock import Mock 6 | 7 | import pytest 8 | 9 | from kombu.transport.consul import Channel, Transport 10 | 11 | pytest.importorskip('consul') 12 | 13 | 14 | class test_Consul: 15 | 16 | def setup_method(self): 17 | self.connection = Mock() 18 | self.connection._used_channel_ids = array('H') 19 | self.connection.channel_max = 65535 20 | self.connection.client.transport_options = {} 21 | self.connection.client.port = 303 22 | self.consul = self.patching('consul.Consul').return_value 23 | self.channel = Channel(connection=self.connection) 24 | 25 | def test_driver_version(self): 26 | assert Transport(self.connection.client).driver_version() 27 | 28 | def test_failed_get(self): 29 | self.channel._acquire_lock = Mock(return_value=False) 30 | self.channel.client.kv.get.return_value = (1, None) 31 | with pytest.raises(Empty): 32 | self.channel._get('empty')() 33 | 34 | def test_test_purge(self): 35 | self.channel._destroy_session = Mock(return_value=True) 36 | self.consul.kv.delete = Mock(return_value=True) 37 | assert self.channel._purge('foo') 38 | 39 | def test_variables(self): 40 | assert self.channel.session_ttl == 30 41 | assert self.channel.timeout == '10s' 42 | 43 | def test_lock_key(self): 44 | key = self.channel._lock_key('myqueue') 45 | assert key == 'kombu/myqueue.lock' 46 | 47 | def test_key_prefix(self): 48 | key = self.channel._key_prefix('myqueue') 49 | assert key == 'kombu/myqueue' 50 | 51 | def test_get_or_create_session(self): 52 | queue = 'myqueue' 53 | session_id = '123456' 54 | self.consul.session.create.return_value = session_id 55 | assert self.channel._get_or_create_session(queue) == session_id 56 | 57 | def test_create_delete_queue(self): 58 | queue = 'mynewqueue' 59 | 60 | self.consul.kv.put.return_value = True 61 | assert self.channel._new_queue(queue) 62 | 63 | self.consul.kv.delete.return_value = True 64 | self.channel._destroy_session = Mock() 65 | self.channel._delete(queue) 66 | 67 | def test_size(self): 68 | self.consul.kv.get.return_value = [(1, {}), (2, {})] 69 | assert self.channel._size('q') == 2 70 | 71 | def test_get(self): 72 | self.channel._obtain_lock = Mock(return_value=True) 73 | self.channel._release_lock = Mock(return_value=True) 74 | 75 | self.consul.kv.get.return_value = [1, [ 76 | {'Key': 'myqueue', 'ModifyIndex': 1, 'Value': '1'}, 77 | ]] 78 | 79 | self.consul.kv.delete.return_value = True 80 | 81 | assert self.channel._get('myqueue') is not None 82 | 83 | def test_put(self): 84 | self.consul.kv.put.return_value = True 85 | assert self.channel._put('myqueue', 'mydata') is None 86 | -------------------------------------------------------------------------------- /t/unit/transport/test_etcd.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from array import array 4 | from queue import Empty 5 | from unittest.mock import Mock, patch 6 | 7 | import pytest 8 | 9 | from kombu.transport.etcd import Channel, Transport 10 | 11 | pytest.importorskip('etcd') 12 | 13 | 14 | class test_Etcd: 15 | 16 | def setup_method(self): 17 | self.connection = Mock() 18 | self.connection._used_channel_ids = array('H') 19 | self.connection.channel_max = 65535 20 | self.connection.client.transport_options = {} 21 | self.connection.client.port = 2739 22 | self.client = self.patching('etcd.Client').return_value 23 | self.channel = Channel(connection=self.connection) 24 | 25 | def test_driver_version(self): 26 | assert Transport(self.connection.client).driver_version() 27 | 28 | def test_failed_get(self): 29 | self.channel._acquire_lock = Mock(return_value=False) 30 | self.channel.client.read.side_effect = IndexError 31 | with patch('etcd.Lock'): 32 | with pytest.raises(Empty): 33 | self.channel._get('empty')() 34 | 35 | def test_test_purge(self): 36 | with patch('etcd.Lock'): 37 | self.client.delete = Mock(return_value=True) 38 | assert self.channel._purge('foo') 39 | 40 | def test_key_prefix(self): 41 | key = self.channel._key_prefix('myqueue') 42 | assert key == 'kombu/myqueue' 43 | 44 | def test_create_delete_queue(self): 45 | queue = 'mynewqueue' 46 | 47 | with patch('etcd.Lock'): 48 | self.client.write.return_value = self.patching('etcd.EtcdResult') 49 | assert self.channel._new_queue(queue) 50 | 51 | self.client.delete.return_value = self.patching('etcd.EtcdResult') 52 | self.channel._delete(queue) 53 | 54 | def test_size(self): 55 | with patch('etcd.Lock'): 56 | self.client.read.return_value = self.patching( 57 | 'etcd.EtcdResult', _children=[{}, {}]) 58 | assert self.channel._size('q') == 2 59 | 60 | def test_get(self): 61 | with patch('etcd.Lock'): 62 | self.client.read.return_value = self.patching( 63 | 'etcd.EtcdResult', 64 | _children=[{'key': 'myqueue', 'modifyIndex': 1, 'value': '1'}]) 65 | assert self.channel._get('myqueue') is not None 66 | 67 | def test_put(self): 68 | with patch('etcd.Lock'): 69 | self.client.write.return_value = self.patching('etcd.EtcdResult') 70 | assert self.channel._put('myqueue', 'mydata') is None 71 | -------------------------------------------------------------------------------- /t/unit/transport/test_pyro.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import socket 4 | 5 | import pytest 6 | 7 | from kombu import Connection, Consumer, Exchange, Producer, Queue 8 | 9 | 10 | class test_PyroTransport: 11 | 12 | def setup_method(self): 13 | self.c = Connection(transport='pyro', virtual_host="kombu.broker") 14 | self.e = Exchange('test_transport_pyro') 15 | self.q = Queue('test_transport_pyro', 16 | exchange=self.e, 17 | routing_key='test_transport_pyro') 18 | self.q2 = Queue('test_transport_pyro2', 19 | exchange=self.e, 20 | routing_key='test_transport_pyro2') 21 | self.fanout = Exchange('test_transport_pyro_fanout', type='fanout') 22 | self.q3 = Queue('test_transport_pyro_fanout1', 23 | exchange=self.fanout) 24 | self.q4 = Queue('test_transport_pyro_fanout2', 25 | exchange=self.fanout) 26 | 27 | def test_driver_version(self): 28 | assert self.c.transport.driver_version() 29 | 30 | @pytest.mark.skip("requires running Pyro nameserver and Kombu Broker") 31 | def test_produce_consume_noack(self): 32 | channel = self.c.channel() 33 | producer = Producer(channel, self.e) 34 | consumer = Consumer(channel, self.q, no_ack=True) 35 | 36 | for i in range(10): 37 | producer.publish({'foo': i}, routing_key='test_transport_pyro') 38 | 39 | _received = [] 40 | 41 | def callback(message_data, message): 42 | _received.append(message) 43 | 44 | consumer.register_callback(callback) 45 | consumer.consume() 46 | 47 | while 1: 48 | if len(_received) == 10: 49 | break 50 | self.c.drain_events() 51 | 52 | assert len(_received) == 10 53 | 54 | def test_drain_events(self): 55 | with pytest.raises(socket.timeout): 56 | self.c.drain_events(timeout=0.1) 57 | 58 | c1 = self.c.channel() 59 | c2 = self.c.channel() 60 | 61 | with pytest.raises(socket.timeout): 62 | self.c.drain_events(timeout=0.1) 63 | 64 | del c1 # so pyflakes doesn't complain. 65 | del c2 66 | 67 | @pytest.mark.skip("requires running Pyro nameserver and Kombu Broker") 68 | def test_drain_events_unregistered_queue(self): 69 | c1 = self.c.channel() 70 | producer = self.c.Producer() 71 | consumer = self.c.Consumer([self.q2]) 72 | 73 | producer.publish( 74 | {'hello': 'world'}, 75 | declare=consumer.queues, 76 | routing_key=self.q2.routing_key, 77 | exchange=self.q2.exchange, 78 | ) 79 | message = consumer.queues[0].get()._raw 80 | 81 | class Cycle: 82 | 83 | def get(self, callback, timeout=None): 84 | return (message, 'foo'), c1 85 | 86 | self.c.transport.cycle = Cycle() 87 | self.c.drain_events() 88 | 89 | @pytest.mark.skip("requires running Pyro nameserver and Kombu Broker") 90 | def test_queue_for(self): 91 | chan = self.c.channel() 92 | x = chan._queue_for('foo') 93 | assert x 94 | assert chan._queue_for('foo') is x 95 | -------------------------------------------------------------------------------- /t/unit/transport/test_sqlalchemy.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from unittest.mock import Mock, patch 4 | 5 | import pytest 6 | 7 | from kombu import Connection 8 | from kombu.exceptions import OperationalError 9 | 10 | pytest.importorskip('sqlalchemy') 11 | 12 | 13 | class test_SqlAlchemy: 14 | 15 | def test_url_parser(self): 16 | with patch('kombu.transport.sqlalchemy.Channel._open'): 17 | url = 'sqlalchemy+sqlite:///celerydb.sqlite' 18 | Connection(url).connect() 19 | 20 | url = 'sqla+sqlite:///celerydb.sqlite' 21 | Connection(url).connect() 22 | 23 | url = 'sqlb+sqlite:///celerydb.sqlite' 24 | with pytest.raises(KeyError): 25 | Connection(url).connect() 26 | 27 | def test_simple_queueing(self): 28 | conn = Connection( 29 | 'sqlalchemy+sqlite:///:memory:', 30 | transport_options={ 31 | "callback": Mock(), 32 | "errback": Mock(), 33 | "max_retries": 20, 34 | "interval_start": 1, 35 | "interval_step": 2, 36 | "interval_max": 30, 37 | "retry_errors": (OperationalError,) 38 | }) 39 | conn.connect() 40 | try: 41 | channel = conn.channel() 42 | assert channel.queue_cls.__table__.name == 'kombu_queue' 43 | assert channel.message_cls.__table__.name == 'kombu_message' 44 | 45 | channel._put('celery', 'DATA_SIMPLE_QUEUEING') 46 | assert channel._get('celery') == 'DATA_SIMPLE_QUEUEING' 47 | finally: 48 | conn.release() 49 | 50 | def test_clone(self): 51 | hostname = 'sqlite:///celerydb.sqlite' 52 | x = Connection('+'.join(['sqla', hostname])) 53 | try: 54 | assert x.uri_prefix == 'sqla' 55 | assert x.hostname == hostname 56 | clone = x.clone() 57 | try: 58 | assert clone.hostname == hostname 59 | assert clone.uri_prefix == 'sqla' 60 | finally: 61 | clone.release() 62 | finally: 63 | x.release() 64 | -------------------------------------------------------------------------------- /t/unit/transport/test_transport.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from unittest.mock import Mock, patch 4 | 5 | from kombu import transport 6 | 7 | 8 | class test_supports_librabbitmq: 9 | 10 | def test_eventlet(self): 11 | with patch('kombu.transport._detect_environment') as de: 12 | de.return_value = 'eventlet' 13 | assert not transport.supports_librabbitmq() 14 | 15 | 16 | class test_transport: 17 | 18 | def test_resolve_transport(self): 19 | from kombu.transport.memory import Transport 20 | assert transport.resolve_transport( 21 | 'kombu.transport.memory:Transport') is Transport 22 | assert transport.resolve_transport(Transport) is Transport 23 | 24 | def test_resolve_transport_alias_callable(self): 25 | m = transport.TRANSPORT_ALIASES['George'] = Mock(name='lazyalias') 26 | try: 27 | transport.resolve_transport('George') 28 | m.assert_called_with() 29 | finally: 30 | transport.TRANSPORT_ALIASES.pop('George') 31 | 32 | def test_resolve_transport_alias(self): 33 | assert transport.resolve_transport('pyamqp') 34 | -------------------------------------------------------------------------------- /t/unit/transport/test_zookeeper.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pytest 4 | 5 | from kombu import Connection 6 | from kombu.transport import zookeeper 7 | 8 | pytest.importorskip('kazoo') 9 | 10 | 11 | class test_Channel: 12 | def setup_method(self): 13 | self.connection = self.create_connection() 14 | self.channel = self.connection.default_channel 15 | 16 | def create_connection(self, **kwargs): 17 | return Connection(transport=zookeeper.Transport, **kwargs) 18 | 19 | def teardown_method(self): 20 | self.connection.close() 21 | 22 | def test_put_puts_bytes_to_queue(self): 23 | class AssertQueue: 24 | def put(self, value, priority): 25 | assert isinstance(value, bytes) 26 | 27 | self.channel._queues['foo'] = AssertQueue() 28 | self.channel._put(queue='foo', message='bar') 29 | 30 | @pytest.mark.parametrize('input,expected', ( 31 | ('', '/'), 32 | ('/root', '/root'), 33 | ('/root/', '/root'), 34 | )) 35 | def test_virtual_host_normalization(self, input, expected): 36 | with self.create_connection(virtual_host=input) as conn: 37 | assert conn.default_channel._vhost == expected 38 | -------------------------------------------------------------------------------- /t/unit/transport/virtual/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/unit/transport/virtual/__init__.py -------------------------------------------------------------------------------- /t/unit/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/celery/kombu/67588f8aa7cc6d561f786440485885de5d0753d3/t/unit/utils/__init__.py -------------------------------------------------------------------------------- /t/unit/utils/test_amq_manager.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from unittest.mock import patch 4 | 5 | import pytest 6 | 7 | from kombu import Connection 8 | 9 | 10 | class test_get_manager: 11 | 12 | @pytest.mark.masked_modules('pyrabbit') 13 | def test_without_pyrabbit(self, mask_modules): 14 | with pytest.raises(ImportError): 15 | Connection('amqp://').get_manager() 16 | 17 | @pytest.mark.ensured_modules('pyrabbit') 18 | def test_with_pyrabbit(self, module_exists): 19 | with patch('pyrabbit.Client', create=True) as Client: 20 | manager = Connection('amqp://').get_manager() 21 | assert manager is not None 22 | Client.assert_called_with( 23 | 'localhost:15672', 'guest', 'guest', 24 | ) 25 | 26 | @pytest.mark.ensured_modules('pyrabbit') 27 | def test_transport_options(self, module_exists): 28 | with patch('pyrabbit.Client', create=True) as Client: 29 | manager = Connection('amqp://', transport_options={ 30 | 'manager_hostname': 'admin.mq.vandelay.com', 31 | 'manager_port': 808, 32 | 'manager_userid': 'george', 33 | 'manager_password': 'bosco', 34 | }).get_manager() 35 | assert manager is not None 36 | Client.assert_called_with( 37 | 'admin.mq.vandelay.com:808', 'george', 'bosco', 38 | ) 39 | -------------------------------------------------------------------------------- /t/unit/utils/test_compat.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import socket 4 | import sys 5 | import types 6 | from unittest.mock import Mock, patch 7 | 8 | import pytest 9 | 10 | from kombu.utils import compat 11 | from kombu.utils.compat import entrypoints, maybe_fileno 12 | 13 | 14 | def test_entrypoints(): 15 | with patch( 16 | 'kombu.utils.compat.importlib_metadata.entry_points', create=True 17 | ) as iterep: 18 | eps = [Mock(), Mock()] 19 | iterep.return_value = ( 20 | {'kombu.test': eps} if sys.version_info < (3, 10) else eps) 21 | 22 | assert list(entrypoints('kombu.test')) 23 | if sys.version_info < (3, 10): 24 | iterep.assert_called_with() 25 | else: 26 | iterep.assert_called_with(group='kombu.test') 27 | eps[0].load.assert_called_with() 28 | eps[1].load.assert_called_with() 29 | 30 | 31 | def test_maybe_fileno(): 32 | assert maybe_fileno(3) == 3 33 | f = Mock(name='file') 34 | assert maybe_fileno(f) is f.fileno() 35 | f.fileno.side_effect = ValueError() 36 | assert maybe_fileno(f) is None 37 | 38 | 39 | class test_detect_environment: 40 | 41 | def test_detect_environment(self): 42 | try: 43 | compat._environment = None 44 | X = compat.detect_environment() 45 | assert compat._environment == X 46 | Y = compat.detect_environment() 47 | assert Y == X 48 | finally: 49 | compat._environment = None 50 | 51 | @pytest.mark.ensured_modules('eventlet', 'eventlet.patcher') 52 | def test_detect_environment_eventlet(self, module_exists): 53 | with patch('eventlet.patcher.is_monkey_patched', create=True) as m: 54 | assert sys.modules['eventlet'] 55 | m.return_value = True 56 | env = compat._detect_environment() 57 | m.assert_called_with(socket) 58 | assert env == 'eventlet' 59 | 60 | @pytest.mark.ensured_modules('gevent') 61 | def test_detect_environment_gevent(self, module_exists): 62 | with patch('gevent.socket', create=True) as m: 63 | prev, socket.socket = socket.socket, m.socket 64 | try: 65 | assert sys.modules['gevent'] 66 | env = compat._detect_environment() 67 | assert env == 'gevent' 68 | finally: 69 | socket.socket = prev 70 | 71 | def test_detect_environment_no_eventlet_or_gevent(self): 72 | try: 73 | sys.modules['eventlet'] = types.ModuleType('eventlet') 74 | sys.modules['eventlet.patcher'] = types.ModuleType('patcher') 75 | assert compat._detect_environment() == 'default' 76 | finally: 77 | sys.modules.pop('eventlet.patcher', None) 78 | sys.modules.pop('eventlet', None) 79 | compat._detect_environment() 80 | try: 81 | sys.modules['gevent'] = types.ModuleType('gevent') 82 | assert compat._detect_environment() == 'default' 83 | finally: 84 | sys.modules.pop('gevent', None) 85 | compat._detect_environment() 86 | -------------------------------------------------------------------------------- /t/unit/utils/test_debug.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import logging 4 | from unittest.mock import Mock, patch 5 | 6 | from kombu.utils.debug import Logwrapped, setup_logging 7 | 8 | 9 | class test_setup_logging: 10 | 11 | def test_adds_handlers_sets_level(self): 12 | with patch('kombu.utils.debug.get_logger') as get_logger: 13 | logger = get_logger.return_value = Mock() 14 | setup_logging(loggers=['kombu.test']) 15 | 16 | get_logger.assert_called_with('kombu.test') 17 | 18 | logger.addHandler.assert_called() 19 | logger.setLevel.assert_called_with(logging.DEBUG) 20 | 21 | 22 | class test_Logwrapped: 23 | 24 | def test_wraps(self): 25 | with patch('kombu.utils.debug.get_logger') as get_logger: 26 | logger = get_logger.return_value = Mock() 27 | 28 | W = Logwrapped(Mock(), 'kombu.test') 29 | get_logger.assert_called_with('kombu.test') 30 | assert W.instance is not None 31 | assert W.logger is logger 32 | 33 | W.instance.__repr__ = lambda s: 'foo' 34 | assert repr(W) == 'foo' 35 | W.instance.some_attr = 303 36 | assert W.some_attr == 303 37 | 38 | W.instance.some_method.__name__ = 'some_method' 39 | W.some_method(1, 2, kw=1) 40 | W.instance.some_method.assert_called_with(1, 2, kw=1) 41 | 42 | W.some_method() 43 | W.instance.some_method.assert_called_with() 44 | 45 | W.some_method(kw=1) 46 | W.instance.some_method.assert_called_with(kw=1) 47 | 48 | W.ident = 'ident' 49 | W.some_method(kw=1) 50 | logger.debug.assert_called() 51 | assert 'ident' in logger.debug.call_args[0][0] 52 | 53 | assert dir(W) == dir(W.instance) 54 | -------------------------------------------------------------------------------- /t/unit/utils/test_div.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import pickle 4 | from io import BytesIO, StringIO 5 | 6 | from kombu.utils.div import emergency_dump_state 7 | 8 | 9 | class MyStringIO(StringIO): 10 | 11 | def close(self): 12 | pass 13 | 14 | 15 | class MyBytesIO(BytesIO): 16 | 17 | def close(self): 18 | pass 19 | 20 | 21 | class test_emergency_dump_state: 22 | 23 | def test_dump(self, stdouts): 24 | fh = MyBytesIO() 25 | stderr = StringIO() 26 | emergency_dump_state( 27 | {'foo': 'bar'}, open_file=lambda n, m: fh, stderr=stderr) 28 | assert pickle.loads(fh.getvalue()) == {'foo': 'bar'} 29 | assert stderr.getvalue() 30 | assert not stdouts.stdout.getvalue() 31 | 32 | def test_dump_second_strategy(self, stdouts): 33 | fh = MyStringIO() 34 | stderr = StringIO() 35 | 36 | def raise_something(*args, **kwargs): 37 | raise KeyError('foo') 38 | 39 | emergency_dump_state( 40 | {'foo': 'bar'}, 41 | open_file=lambda n, m: fh, 42 | dump=raise_something, 43 | stderr=stderr, 44 | ) 45 | assert 'foo' in fh.getvalue() 46 | assert 'bar' in fh.getvalue() 47 | assert stderr.getvalue() 48 | assert not stdouts.stdout.getvalue() 49 | -------------------------------------------------------------------------------- /t/unit/utils/test_encoding.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import sys 4 | from contextlib import contextmanager 5 | from unittest.mock import patch 6 | 7 | from kombu.utils.encoding import (default_encoding, get_default_encoding_file, 8 | safe_str, set_default_encoding_file) 9 | 10 | 11 | @contextmanager 12 | def clean_encoding(): 13 | old_encoding = sys.modules.pop('kombu.utils.encoding', None) 14 | import kombu.utils.encoding 15 | try: 16 | yield kombu.utils.encoding 17 | finally: 18 | if old_encoding: 19 | sys.modules['kombu.utils.encoding'] = old_encoding 20 | 21 | 22 | class test_default_encoding: 23 | 24 | def test_set_default_file(self): 25 | prev = get_default_encoding_file() 26 | try: 27 | set_default_encoding_file('/foo.txt') 28 | assert get_default_encoding_file() == '/foo.txt' 29 | finally: 30 | set_default_encoding_file(prev) 31 | 32 | @patch('sys.getfilesystemencoding') 33 | def test_default(self, getdefaultencoding): 34 | getdefaultencoding.return_value = 'ascii' 35 | with clean_encoding() as encoding: 36 | enc = encoding.default_encoding() 37 | if sys.platform.startswith('java'): 38 | assert enc == 'utf-8' 39 | else: 40 | assert enc == 'ascii' 41 | getdefaultencoding.assert_called_with() 42 | 43 | 44 | class newbytes(bytes): 45 | """Mock class to simulate python-future newbytes class""" 46 | 47 | def __repr__(self): 48 | return 'b' + super().__repr__() 49 | 50 | def __str__(self): 51 | return 'b' + f"'{super().__str__()}'" 52 | 53 | 54 | class newstr(str): 55 | """Mock class to simulate python-future newstr class""" 56 | 57 | def encode(self, encoding=None, errors=None): 58 | return newbytes(super().encode(encoding, errors)) 59 | 60 | 61 | class test_safe_str: 62 | 63 | def setup_method(self): 64 | self._encoding = self.patching('sys.getfilesystemencoding') 65 | self._encoding.return_value = 'ascii' 66 | 67 | def test_when_bytes(self): 68 | assert safe_str('foo') == 'foo' 69 | 70 | def test_when_newstr(self): 71 | """Simulates using python-future package under 2.7""" 72 | assert str(safe_str(newstr('foo'))) == 'foo' 73 | 74 | def test_when_unicode(self): 75 | assert isinstance(safe_str('foo'), str) 76 | 77 | def test_when_encoding_utf8(self): 78 | self._encoding.return_value = 'utf-8' 79 | assert default_encoding() == 'utf-8' 80 | s = 'The quiæk fåx jømps øver the lazy dåg' 81 | res = safe_str(s) 82 | assert isinstance(res, str) 83 | 84 | def test_when_containing_high_chars(self): 85 | self._encoding.return_value = 'ascii' 86 | s = 'The quiæk fåx jømps øver the lazy dåg' 87 | res = safe_str(s) 88 | assert isinstance(res, str) 89 | assert len(s) == len(res) 90 | 91 | def test_when_not_string(self): 92 | o = object() 93 | assert safe_str(o) == repr(o) 94 | 95 | def test_when_unrepresentable(self): 96 | 97 | class UnrepresentableObject: 98 | 99 | def __repr__(self): 100 | raise KeyError('foo') 101 | 102 | assert ' None: 9 | assert uuid() != uuid() 10 | 11 | def test_uuid(self) -> None: 12 | i1 = uuid() 13 | i2 = uuid() 14 | assert isinstance(i1, str) 15 | assert i1 != i2 16 | --------------------------------------------------------------------------------