pax_global_header00006660000000000000000000000064134561522670014525gustar00rootroot0000000000000052 comment=f3c1f5ccd9dacb56693bd8737b0e16d886ab65e0 pamqp-2.3.0/000077500000000000000000000000001345615226700126455ustar00rootroot00000000000000pamqp-2.3.0/.checkignore000066400000000000000000000000421345615226700151230ustar00rootroot00000000000000tests docs codegen tools setup.py pamqp-2.3.0/.codeclimate.yml000066400000000000000000000002021345615226700157110ustar00rootroot00000000000000languages: Python: true exclude_paths: - codegen/* - docs/* - pamqp/specification.py - tests/* - tools/* pamqp-2.3.0/.gitignore000066400000000000000000000003151345615226700146340ustar00rootroot00000000000000.idea .vscode codegen/amqp-rabbitmq-0.9.1.json codegen/amqp0-9-1.xml *.pyc build dist docs/_build atlassian-ide-plugin.xml .DS_Store pamqp.egg-info env env2.7 env3 .coverage coverage.xml xunit.xml coveragepamqp-2.3.0/.travis.yml000066400000000000000000000026561345615226700147670ustar00rootroot00000000000000language: python dist: xenial python: - 2.7 - 3.4 - 3.5 - 3.6 - 3.7 env: global: - PATH=$HOME/.local/bin:$PATH - AWS_DEFAULT_REGION=us-east-1 - secure: "H1xbz9QUvgoNtDvY9K72YvUkGGVWiq5qL2IZDfG1y7scIKdUMZqvj2s/aB/UCw95POc1/SSo1vf5rtpvz7D4TTo+YW9y9ZLuHxetbGPnkql+lu/+HTpPJcr91pg4fEz4txhnAlJ+cdp3bITOvbuKYoUZ+toxiTf3wouETBikfGo=" - secure: "JZRJyA7fGSHjEx8nIyCzhD9KLWbu4h1R5A+VLDuFN0FjCjALKjJxaIUwT8/xHT97FXbqTbN+xvFyWnKerVpGX1peNGifralm3tMl63QXdATaprsmENmM3fYRWYGqWhy+6a21hrxFZ+MdblFKWsFWq/TNbsLWYM3vahvZDe1eyck=" stages: - test - name: upload coverage if: repo = gmr/pamqp - name: deploy if: tag IS present install: - pip install -r requirements.txt - pip install awscli script: - nosetests - flake8 after_success: bin/upload-coverage.sh jobs: include: - stage: upload coverage if: repo = gmr/pamqp python: 3.6 install: - pip install awscli coverage codecov script: bin/combine-coverage.sh after_success: codecov - stage: deploy python: 3.6 install: true script: true after_success: true deploy: distributions: sdist bdist_wheel provider: pypi user: crad on: tags: true password: secure: "HW5Ak3scfeQ1/qdXQYrmIVnpGex59qNSGN2WRoHSFMXLfsjzdBQccy2nxWAo7p6P1wgoZ/51lTamJXGKgVqqQGC3gfBiD+AVMu3CROQht+Q4x5xKKLXQtTBoEOpurnx7q0oXRxhK7qmMOek9qqn/GGrK5PJV+pGoPwCvSTF6aic=" pamqp-2.3.0/CONTRIBUTING.md000066400000000000000000000006761345615226700151070ustar00rootroot00000000000000# Contributing To get setup in the environment and run the tests, take the following steps: ```bash virtualenv -p python3 env source env/bin/activate pip install -r requirements.txt nosetests flake8 ``` Please format your code contributions with the ``yapf`` formatter: ```bash yapf -i --style=pep8 pamqp ``` ## Test Coverage Pull requests that make changes or additions that are not covered by tests will likely be closed without review. pamqp-2.3.0/LICENSE000066400000000000000000000027211345615226700136540ustar00rootroot00000000000000Copyright (c) 2011-2015 Gavin M. Roy All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the paqmp nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. pamqp-2.3.0/MANIFEST.in000066400000000000000000000000431345615226700144000ustar00rootroot00000000000000include README.rst include LICENSE pamqp-2.3.0/README.rst000066400000000000000000000017401345615226700143360ustar00rootroot00000000000000pamqp ===== pamqp is a pure-python AMQP 0-9-1 frame encoder and decoder. The aim is to create a client agnostic python encoder and decoder for general purpose use. |Version| |Status| |Coverage| |License| Documentation ------------- http://pamqp.readthedocs.org License ------- BSD Python Versions Supported ------------------------- 2.7, 3.4+ Roadmap ------- pamqp 3.0 will drop support for Python 2.7 and will be released after January 1st, 2020. Requirements ------------ codegen (not required for use) requires lxml. .. |Version| image:: https://img.shields.io/pypi/v/pamqp.svg? :target: https://pypi.python.org/pypi/pamqp .. |Status| image:: https://img.shields.io/travis/gmr/pamqp.svg? :target: https://travis-ci.org/gmr/pamqp .. |Coverage| image:: https://img.shields.io/codecov/c/github/gmr/pamqp.svg? :target: https://codecov.io/github/gmr/pamqp?branch=master .. |License| image:: https://img.shields.io/pypi/l/pamqp.svg? :target: https://pamqp.readthedocs.org pamqp-2.3.0/bin/000077500000000000000000000000001345615226700134155ustar00rootroot00000000000000pamqp-2.3.0/bin/combine-coverage.sh000077500000000000000000000003011345615226700171530ustar00rootroot00000000000000#!/usr/bin/env sh mkdir coverage aws s3 cp --recursive s3://com-gavinroy-travis/pamqp/${TRAVIS_BUILD_NUMBER}/ coverage cd coverage coverage combine cd .. mv coverage/.coverage . coverage reportpamqp-2.3.0/bin/upload-coverage.sh000077500000000000000000000003671345615226700170370ustar00rootroot00000000000000#!/usr/bin/env sh if [ "${TRAVIS_REPO_SLUG}" = "gmr/pamqp" ]; then echo "Uploading coverage for ${TRAVIS_PYTHON_VERSION} to S3" aws s3 cp .coverage "s3://com-gavinroy-travis/pamqp/$TRAVIS_BUILD_NUMBER/.coverage.${TRAVIS_PYTHON_VERSION}" fipamqp-2.3.0/codegen/000077500000000000000000000000001345615226700142515ustar00rootroot00000000000000pamqp-2.3.0/codegen/extensions.xml000066400000000000000000000061701345615226700171760ustar00rootroot00000000000000 This method signals to the client that the connection is blocked by RabbitMQ. This method signals to the client that the connection is no longer blocked by RabbitMQ. do not send a reply method If set, the server will not respond to the method. The client should not wait for a reply method. If the server could not complete the method it will raise a channel or connection exception. Deprecated value that must be zero. Deprecated value that must be empty. Deprecated value that must be False. Used when negotiating a connection on an out-of-band channel. Do not use, must be zero. Deprecated value that must be False. Deprecated value that must be zero. If set, the queue is deleted when all consumers have finished using it. The last consumer can be cancelled either explicitly or because its channel is closed. If there was no consumer ever on the queue, it won't be deleted. Applications can explicitly delete auto-delete queues using the Delete method as normal. Deprecated value that must be zero. Deprecated value that must be zero. pamqp-2.3.0/codegen/include.py000066400000000000000000000162131345615226700162510ustar00rootroot00000000000000 class Frame(object): """Base Class for AMQP Methods which specifies the encoding and decoding behavior. """ __slots__ = [] frame_id = 0 index = 0 name = 'Frame' synchronous = False valid_responses = [] def __iter__(self): """Iterate the attributes and values as key, value pairs. :rtype: tuple """ for attribute in self.__slots__: yield (attribute, getattr(self, attribute)) def __contains__(self, item): """Return if the item is in the attribute list. :rtype: bool """ return item in self.__slots__ def __getitem__(self, item): """Return an attribute as if it were a dict. :param str item: The item to look for :raises: KeyError :rtype: any """ return getattr(self, item) def __len__(self): """Return the length of the attribute list. :rtype: int """ return len(self.__slots__) def __repr__(self): """Return the representation of the frame object :return: str """ return '<%s.%s object at %s>' % (__name__, self.name, hex(id(self))) @classmethod def type(cls, attr): """Return the data type for an attribute. :rtype: str """ return getattr(cls, '_' + attr) def marshal(self): """ Dynamically encode the frame by taking the list of attributes and encode them item by item getting the value form the object attribute and the data type from the class attribute. :rtype: str """ output = [] processing_bitset = False byte = None offset = 0 for argument in self.__slots__: data_type = self.type(argument) # Check if we need to turn on bit processing if not processing_bitset and data_type == 'bit': byte = 0 offset = 0 processing_bitset = True # Get the data value data_value = getattr(self, argument) # If we're processing a bitset, apply special rules if processing_bitset: # Is this value not a bit? turn off bitset processing and # append the byte value as an octet if data_type != 'bit': processing_bitset = False output.append(encode.octet(byte)) else: # Apply the bit value to the byte byte = encode.bit(data_value, byte, offset) offset += 1 if offset == 8: # We've filled a byte for all bits, add the byte output.append(encode.octet(byte)) # Turn off processing, we'll turn on in next iteration # if needed processing_bitset = False # Go to the next iteration continue # Not a bit, so just process by type output.append(encode.by_type(data_value, data_type)) # Append the last byte if we're processing a bitset if processing_bitset: output.append(encode.octet(byte)) return b''.join(output) def unmarshal(self, data): """ Dynamically decode the frame data applying the values to the method object by iterating through the attributes in order and decoding them. :param str data: The binary encoded method data """ offset = 0 processing_bitset = False for argument in self.__slots__: data_type = self.type(argument) if offset == 7 and processing_bitset: data = data[1:] offset = 0 if processing_bitset and data_type != 'bit': offset = 0 processing_bitset = False data = data[1:] consumed, value = decode.by_type(data, data_type, offset) if data_type == 'bit': offset += 1 processing_bitset = True consumed = 0 setattr(self, argument, value) if consumed: data = data[consumed:] class PropertiesBase(object): """Provide a base object that marshals and unmarshals the Basic.Properties object values. """ __slots__ = [] flags = {} name = 'PropertiesBase' def __contains__(self, item): return item in self.__slots__ def __delattr__(self, item): setattr(self, item, None) def __iter__(self): """Iterate the attributes and values as key, value pairs. :rtype: tuple """ for attribute in self.__slots__: yield (attribute, getattr(self, attribute)) @classmethod def attributes(cls): """Return the list of attributes :rtype: list """ return [attr for attr in cls.__slots__] @classmethod def type(cls, attr): """Return the data type for an attribute. :rtype: str """ return getattr(cls, '_' + attr) def encode_property(self, property_name, property_value): """Encode a single property value :param str property_name: The property name to encode :param any property_value: The value to encode """ return encode.by_type(property_value, self.type(property_name)) def marshal(self): """Take the Basic.Properties data structure and marshal it into the data structure needed for the ContentHeader. :rtype: bytes """ flags = 0 parts = [] for property_name in self.__slots__: property_value = getattr(self, property_name) if property_value is not None and property_value != '': flags = flags | self.flags[property_name] parts.append(self.encode_property(property_name, property_value)) flag_pieces = [] while True: remainder = flags >> 16 partial_flags = flags & 0xFFFE if remainder != 0: partial_flags |= 1 flag_pieces.append(struct.pack('>H', partial_flags)) flags = remainder if not flags: break return b''.join(flag_pieces + parts) def to_dict(self): """Return the properties as a dict :rtype: dict """ return dict(self) def unmarshal(self, flags, data): """ Dynamically decode the frame data applying the values to the method object by iterating through the attributes in order and decoding them. :param int flags: Flags that indicate if the data has the property :param bytes data: The binary encoded method data """ for property_name in self.__slots__: if flags & self.flags[property_name]: data_type = getattr(self.__class__, '_' + property_name) consumed, value = decode.by_type(data, data_type) setattr(self, property_name, value) data = data[consumed:] pamqp-2.3.0/docs/000077500000000000000000000000001345615226700135755ustar00rootroot00000000000000pamqp-2.3.0/docs/Makefile000066400000000000000000000126701345615226700152430ustar00rootroot00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " texinfo to make Texinfo files" @echo " info to make Texinfo files and run them through makeinfo" @echo " gettext to make PO message catalogs" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pamqp.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pamqp.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/pamqp" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pamqp" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @echo "Run \`make' in that directory to run these through makeinfo" \ "(use \`make info' here to do that automatically)." info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." pamqp-2.3.0/docs/body.rst000066400000000000000000000000771345615226700152700ustar00rootroot00000000000000pamqp.body ========== .. automodule:: pamqp.body :members: pamqp-2.3.0/docs/conf.py000066400000000000000000000172251345615226700151030ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # pamqp documentation build configuration file, created by # sphinx-quickstart on Wed Mar 27 13:26:28 2013. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os sys.path.insert(0, '../') # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. #sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.autosummary'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'pamqp' copyright = u'2011 - 2014, Gavin M. Roy' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. import pamqp release = pamqp.__version__ version = '.'.join(release.split('.')[0:1]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. show_authors = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'pamqpdoc' # -- Options for LaTeX output -------------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). #'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). #'pointsize': '10pt', # Additional stuff for the LaTeX preamble. #'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'pamqp.tex', u'pamqp Documentation', u'Gavin M. Roy', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'pamqp', u'pamqp Documentation', [u'Gavin M. Roy'], 1) ] # If true, show URL addresses after external links. #man_show_urls = False # -- Options for Texinfo output ------------------------------------------------ # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'pamqp', u'pamqp Documentation', u'Gavin M. Roy', 'pamqp', 'AMQP Frame Encoding and Decoding Library.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. #texinfo_appendices = [] # If false, no module index is generated. #texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. #texinfo_show_urls = 'footnote' pamqp-2.3.0/docs/decode.rst000066400000000000000000000001051345615226700155460ustar00rootroot00000000000000pamqp.decode ============ .. automodule:: pamqp.decode :members: pamqp-2.3.0/docs/encode.rst000066400000000000000000000001051345615226700155600ustar00rootroot00000000000000pamqp.encode ============ .. automodule:: pamqp.encode :members: pamqp-2.3.0/docs/frame.rst000066400000000000000000000001021345615226700154120ustar00rootroot00000000000000pamqp.frame =========== .. automodule:: pamqp.frame :members: pamqp-2.3.0/docs/header.rst000066400000000000000000000001051345615226700155530ustar00rootroot00000000000000pamqp.header ============ .. automodule:: pamqp.header :members: pamqp-2.3.0/docs/heartbeat.rst000066400000000000000000000001161345615226700162640ustar00rootroot00000000000000pamqp.heartbeat =============== .. automodule:: pamqp.heartbeat :members: pamqp-2.3.0/docs/history.rst000066400000000000000000000131111345615226700160250ustar00rootroot00000000000000Version History =============== 2.3.0 (2019-04-18) ------------------ - Add :py:func:`pamqp.encode.support_deprecated_rabbitmq` function to limit data types available when encoding field-tables for older RabbitMQ versions. 2.2.0 (2019-04-18) ------------------ - Change :py:meth:`pamqp.encode.timestamp` to allow for numeric/epoch timestamps (#14 - `mosquito `_) - Change :py:meth:`pamqp.frame.frame_parts` to a public method (#15 - `mosquito `_) - Cleanup of code to pass configured flake8 tests - Add support for 8-bit unsigned integer values in :py:meth:`pamqp.encode.table_integer` 2.1.0 (2018-12-28) ------------------ - Change raising a DeprecationWarning exception to using warnings.warn for deprecated AMQP methods (#13 - `dzen `_) 2.0.0 (2018-09-11) ------------------ - **Change Python versions supported to 2.7 and 3.4+** - **Always decode field table keys as strings (#6)** - This may be a breaking change means in Python3 keys will always be type str for short strings. This includes frame values and field table values. - In Python 2.7 if a short-string (key, frame field value, etc) has UTF-8 characters in it, it will be a `unicode` object. - Combine test coverage across all Python versions - Fix range for signed short integer (#7) - Fix guards for usage of unsigned short usage in `pamqp.encode` (#7) - Fix encoding and decoding of unsigned short (#7) - Add support for unsigned short integer and long integer in field tables (#10) - Address edge case of small value in long type (#8) - Address long string encoding inconsistency (#9) - Cleanup unicode object & conditionals in py3 (#9) - Add `pamqp.exceptions.PAMQPException` as a base class for pamqp specific exceptions (#4) - Fix decoding of void values in a field table or array 1.6.1 (2015-02-05) ------------------ - Fix the encoding guard for unsigned short integers to be 65535 [rabbitpy #62] 1.6.0 (2014-12-12) ------------------ - Remove UTF-8 encoding from byte_array (#2) - Fix AMQP Field Tables / `Basic.Properties` headers behavior: - Field names per spec should not exceed 128 bytes - long-strings should not be utf-8 encoded (only short-strings *boggle*) - Ensure that field table long strings are not coerced to UTF-8 as specified in AMQP 0-9-1 If a string is passed in as a long string in a field table and it contains UTF-8 characters it will be UTF-8 encoded - Move AMQP Methods in specification.py to slotted classes - Change `Basic.Properties` to a slotted class - Instead of class level attributes with the same name as obj attributes, prefix class attributes for data types with an underscore - Add new class method type() for `Basic.Properties` for accessing data type - Add new class method type() for AMQP methods for accessing data type - Change `Basic.Properties.attributes` to `Basic.Properties.attributes()`, returning the list of slotted attributes - Fix a typo for booleans in the method mapping for table decoding - `Frame.__getitem__` will now raise a KeyError instead of None for an invalid attribute - `PropertiesBase` no longer checks to see if an attribute is set for contains - Adds new specification tests - More efficiently handle the frame end character in Python 3 1.5.0 (2014-11-05) ------------------ - Cleanup how UTF-8 is handled in decoding strings - Ensure that field tables (headers property, etc) can use keys with utf-8 data - Address missing and mis-aligned AMQP-0-9-1 field table decoding with the field type indicators from the RabbitMQ protocol errata page - Fix a encoding by type bug introduced with 1.4 having to do with bytearrays - Be explicit about needing a class id in the ContentHeader - Update the tests to reflect the unicode changes - Clean up the tests 1.4.0 (2014-11-04) ------------------ - Fix a long standing bug for non-specified responses for RabbitMQ AMQP extensions - Refactor adding bytearrays and recoding complexity - Add bytearray support (#1 and gmr/rabbitpy#48) - Change encode/decode type errors from ValueError to TypeError exceptions - Remove separate codecs for Python 2 & 3 - Move codecs from `pamqp.codec.encode` and `pamqp.codec.decode` to `pamqp.encode` and `pamqp.decode` - Deprecate pamqp.codec - Remove weird imports from top level __init__.py, not sure what I was thinking there - Clean up codegen a bit to make it more PYTHON3 compatible - Update codegen/include for new codec and PYTHON2/PYTHON3 behavior - Update documentation - Distribution updates: - Let travis upload to pypi - Add wheel distribution - Update supported python versions - Update classifiers 1.3.1 (2014-02-14) ------------------ - Fix encoding of long-long-integers 1.3.0 (2014-01-17) ------------------ - Remove support for short strings in field tables 1.2.4 (2013-12-22) ------------------ - Add short-short-int support 1.2.3 (2013-12-22) ------------------ - Fix distribution requirements 1.2.2 (2013-12-22) ------------------ - Add decimal data type support 1.2.1 (2013-07-29) ------------------ - Fix Confirm.Select definition 1.2.0 (2013-07-08) ------------------ - Add support for Connection.Blocked, Connection.Unblocked - Add documentation to specification.py in the codegen process 1.1.3 (2013-03-27) ------------------ - Fix exception creation 1.1.2 (2013-03-27) ------------------ - Add Confirm.Select, Confirm.SelectOk 1.1.1 (2013-03-22) ------------------ - Remove debugging print statements (eek) 1.1.0 (2013-03-21) ------------------ - Add Python 3.3 support 1.0.1 (2012-10-02) ------------------ - Address Unicode issues - Add void support in table arrays 1.0.0 (2012-09-24) ------------------ - Initial version pamqp-2.3.0/docs/index.rst000066400000000000000000000024141345615226700154370ustar00rootroot00000000000000pamqp ===== pamqp is a low level AMQP 0-9-1 frame encoding and decoding library for Python 2 & 3 released under the BSD license. pamqp is not a end-user client library for talking to RabbitMQ but rather is used by client libraries for marshaling and unmarshaling AMQP frames. All methods should have test coverage and pass in Python 2.7, and 3.4 - 3.7. AMQP class/method command class mappings can be found in the :py:mod:`pamqp.specification` module while actual frame encoding and encoding should be run through the :py:mod:`pamqp.frame` module. Issues ------ Please report any issues to the Github repo at `https://github.com/gmr/pamqp/issues `_ Source ------ pamqp source is available on Github at `https://github.com/gmr/pamqp `_ Installation ------------ pamqp is available from the `Python Package Index `_ but should generally be installed as a dependency from a client library. pamqp module documentation -------------------------- .. toctree:: :maxdepth: 2 body decode encode frame header heartbeat specification Version History --------------- See :doc:`history` Indices and tables ------------------ * :ref:`genindex` * :ref:`modindex` * :ref:`search` pamqp-2.3.0/docs/specification.rst000066400000000000000000000017141345615226700171520ustar00rootroot00000000000000pamqp.specification =================== The :py:mod:`pamqp.specification` module is auto-generated, created by the ``tools/codegen.py`` application. It contains all of the information about the protocol that is required for a client library to communicate with RabbitMQ or another AMQP 0-9-1 broker. The classes inside :py:mod:`pamqp.specification` allow for the automatic marshaling and unmarshaling of AMQP method frames and Basic.Properties. In addition the command classes contain information that designates if they are synchronous commands and if so, what the expected responses are. Each commands arguments are detailed in the class and are listed in the attributes property. :py:mod:`pamqp.specification` also implements AMQP exceptions as Python exceptions so that client libraries can raise these exceptions as is appropriate without having to implement their own extensions for AMQP protocol related issues. .. automodule:: pamqp.specification :members: pamqp-2.3.0/pamqp/000077500000000000000000000000001345615226700137635ustar00rootroot00000000000000pamqp-2.3.0/pamqp/__init__.py000066400000000000000000000006641345615226700161020ustar00rootroot00000000000000# -*- encoding: utf-8 -*- """AMQP Specifications and Classes""" from pamqp.constants import PYTHON3 from pamqp.header import ContentHeader, ProtocolHeader __author__ = 'Gavin M. Roy' __email__ = 'gavinmroy@gmail.com' __since__ = '2011-09-23' __version__ = '2.3.0' __all__ = [ 'body', 'constants', 'decode', 'encode', 'exceptions', 'frame', 'header', 'heartbeat', 'specification', 'PYTHON3', 'ContentHeader', 'ProtocolHeader' ] pamqp-2.3.0/pamqp/body.py000066400000000000000000000024251345615226700152750ustar00rootroot00000000000000# -*- encoding: utf-8 -*- """ The pamqp.body module contains the Body class which is used when unmarshaling body frames. When dealing with content frames, the message body will be returned from the library as an instance of the body class. """ class ContentBody(object): """ContentBody carries the value for an AMQP message body frame""" name = 'ContentBody' def __init__(self, value=None): """Create a new instance of a ContentBody object, passing in the value of the message body :param str|unicode|bytes value: The content body """ self.value = value def __len__(self): """Return the length of the content body value :rtype: int """ return len(self.value) def marshal(self): """Return the marshaled content body. This method is here for API compatibility, there is no special marhsaling for the payload in a content frame. :rtype: str|unicode|bytes """ return self.value def unmarshal(self, data): """Apply the data to the object. This method is here for API compatibility, there is no special unmarhsaling for the payload in a content frame. :rtype: str|unicode|bytes """ self.value = data pamqp-2.3.0/pamqp/codec/000077500000000000000000000000001345615226700150405ustar00rootroot00000000000000pamqp-2.3.0/pamqp/codec/__init__.py000066400000000000000000000003431345615226700171510ustar00rootroot00000000000000""" Deprecating the codec subpackage """ import warnings from pamqp import decode, encode warnings.warn('Imports for decode/encode are no longer under codec', DeprecationWarning) __all__ = ['decode', 'encode'] pamqp-2.3.0/pamqp/constants.py000066400000000000000000000002371345615226700163530ustar00rootroot00000000000000""" Common Constants """ import sys # Keep a constant that indicates if Python 3 support is needed PYTHON3 = True if sys.version_info > (3, 0, 0) else False pamqp-2.3.0/pamqp/decode.py000066400000000000000000000260601345615226700155640ustar00rootroot00000000000000# -*- encoding: utf-8 -*- """ AMQP Data Decoder ================= Functions for decoding data of various types including field tables and arrays """ import decimal as _decimal import struct import time from pamqp import PYTHON3 class Struct(object): """Simple object for getting to the struct objects""" byte = struct.Struct('B') double = struct.Struct('>d') float = struct.Struct('>f') integer = struct.Struct('>I') ulong = struct.Struct('>L') long = struct.Struct('>l') ushort = struct.Struct('>H') short = struct.Struct('>h') short_short = struct.Struct('>B') timestamp = struct.Struct('>Q') def bit(value, position): """Decode a bit value :param bytes value: Value to decode :param int position: The bit position to retrieve :return tuple: bytes used, bool value :raises: ValueError """ bit_buffer = Struct.byte.unpack_from(value)[0] try: return 0, (bit_buffer & (1 << position)) != 0 except TypeError: raise ValueError('Could not unpack data') def boolean(value): """Decode a boolean value :param bytes value: Value to decode :return tuple: bytes used, bool :raises: ValueError """ try: return 1, bool(Struct.byte.unpack_from(value[0:1])[0]) except TypeError: raise ValueError('Could not unpack data') def byte_array(value): """Decode a byte_array value :param bytes value: Value to decode :return tuple: bytes used, bool :raises: ValueError """ try: length = Struct.integer.unpack(value[0:4])[0] return length + 4, bytearray(value[4:length + 4]) except TypeError: raise ValueError('Could not unpack data') def decimal(value): """Decode a decimal value :param bytes value: Value to decode :return tuple: bytes used, decimal.Decimal value :raises: ValueError """ try: decimals = Struct.byte.unpack(value[0:1])[0] raw = Struct.integer.unpack(value[1:5])[0] return 5, _decimal.Decimal(raw) * (_decimal.Decimal(10)**-decimals) except TypeError: raise ValueError('Could not unpack data') def double(value): """Decode a double value :param bytes value: Value to decode :return tuple: bytes used, float :raises: ValueError """ try: return 8, Struct.double.unpack_from(value)[0] except TypeError: raise ValueError('Could not unpack data') def floating_point(value): """Decode a floating point value :param bytes value: Value to decode :return tuple: bytes used, float :raises: ValueError """ try: return 4, Struct.float.unpack_from(value)[0] except TypeError: raise ValueError('Could not unpack data') def long_int(value): """Decode a long integer value :param bytes value: Value to decode :return tuple: bytes used, int :raises: ValueError """ try: return 4, Struct.long.unpack(value[0:4])[0] except TypeError: raise ValueError('Could not unpack data') def long_uint(value): """Decode an unsigned long integer value :param bytes value: Value to decode :return tuple: bytes used, int :raises: ValueError """ try: return 4, Struct.ulong.unpack(value[0:4])[0] except TypeError: raise ValueError('Could not unpack data') def long_long_int(value): """Decode a long-long integer value :param bytes value: Value to decode :return tuple: bytes used, int :raises: ValueError """ try: return 8, struct.unpack('>q', value[0:8])[0] except TypeError: raise ValueError('Could not unpack data') def long_str(value): """Decode a string value :param bytes value: Value to decode :return tuple: bytes used, bytes|str :raises: ValueError """ try: length = Struct.integer.unpack(value[0:4])[0] return length + 4, value[4:length + 4] except TypeError: raise ValueError('Could not unpack data') def octet(value): """Decode an octet value :param bytes value: Value to decode :return tuple: bytes used, int :raises: ValueError """ try: return 1, Struct.byte.unpack(value[0:1])[0] except TypeError: raise ValueError('Could not unpack data') def short_int(value): """Decode a short integer value :param bytes value: Value to decode :return tuple: bytes used, int :raises: ValueError """ try: return 2, Struct.short.unpack_from(value[0:2])[0] except TypeError: raise ValueError('Could not unpack data') def short_uint(value): """Decode an unsigned short integer value :param bytes value: Value to decode :return tuple: bytes used, int :raises: ValueError """ try: return 2, Struct.ushort.unpack_from(value[0:2])[0] except TypeError: raise ValueError('Could not unpack data') def short_short_int(value): """Decode a short, short integer value :param bytes value: Value to decode :return tuple: bytes used, int :raises: ValueError """ try: return 1, Struct.short_short.unpack_from(value[0:1])[0] except TypeError: raise ValueError('Could not unpack data') def short_str(value): """Decode a string value :param bytes value: Value to decode :return tuple: bytes used, unicode|str :raises: ValueError """ try: length = Struct.byte.unpack(value[0:1])[0] return length + 1, _to_str(value[1:length + 1]) except TypeError: raise ValueError('Could not unpack data') def timestamp(value): """Decode a timestamp value :param bytes value: Value to decode :return tuple: bytes used, struct_time :raises: ValueError """ try: value = Struct.timestamp.unpack(value[0:8]) return 8, time.gmtime(value[0]) except TypeError: raise ValueError('Could not unpack data') def field_array(value): """Decode a field array value :param bytes value: Value to decode :return tuple: bytes used, list :raises: ValueError """ try: length = Struct.integer.unpack(value[0:4])[0] offset = 4 data = [] field_array_end = offset + length while offset < field_array_end: consumed, result = _embedded_value(value[offset:]) offset += consumed data.append(result) return offset, data except TypeError: raise ValueError('Could not unpack data') def field_table(value): """Decode a field array value :param bytes value: Value to decode :return tuple: bytes used, dict :raises: ValueError """ try: length = Struct.integer.unpack(value[0:4])[0] offset = 4 data = {} field_table_end = offset + length while offset < field_table_end: key_length = Struct.byte.unpack_from(value, offset)[0] offset += 1 key = _to_str(value[offset:offset + key_length]) offset += key_length consumed, result = _embedded_value(value[offset:]) offset += consumed data[key] = result return field_table_end, data except TypeError: raise ValueError('Could not unpack data') def _embedded_value(value): """Takes in a value looking at the first byte to determine which decoder to use :param bytes value: Value to decode :return tuple: bytes consumed, mixed """ if not value: return 0, None # Determine the field type and encode it if value[0:1] == b't': bytes_consumed, value = boolean(value[1:]) elif value[0:1] == b'b': bytes_consumed, value = short_short_int(value[1:]) elif value[0:1] == b's': bytes_consumed, value = short_int(value[1:]) elif value[0:1] == b'u': bytes_consumed, value = short_uint(value[1:]) elif value[0:1] == b'I': bytes_consumed, value = long_int(value[1:]) elif value[0:1] == b'i': bytes_consumed, value = long_uint(value[1:]) elif value[0:1] == b'l': bytes_consumed, value = long_long_int(value[1:]) elif value[0:1] == b'f': bytes_consumed, value = floating_point(value[1:]) elif value[0:1] == b'd': bytes_consumed, value = double(value[1:]) elif value[0:1] == b'D': bytes_consumed, value = decimal(value[1:]) elif value[0:1] == b'S': bytes_consumed, value = long_str(value[1:]) elif value[0:1] == b'A': bytes_consumed, value = field_array(value[1:]) elif value[0:1] == b'T': bytes_consumed, value = timestamp(value[1:]) elif value[0:1] == b'F': bytes_consumed, value = field_table(value[1:]) elif value[0:1] == b'V': bytes_consumed, value = 0, None elif value[0:1] == b'x': bytes_consumed, value = byte_array(value[1:]) elif value[0:1] == b'\x00': return 0, None else: raise ValueError('Unknown type: {!r}'.format(value[:1])) return bytes_consumed + 1, value def by_type(value, data_type, offset=0): """Decodes values using the specified type :param bytes value: Value to decode :param str data_type: type of data to decode :return tuple: bytes consumed, mixed based on field type """ # Determine the field type and encode it data_type = str(data_type) if data_type == 'array': return field_array(value) elif data_type == 'bit': return bit(value, offset) elif data_type == 'boolean': return boolean(value) elif data_type == 'byte_array': return byte_array(value) elif data_type == 'decimal': return decimal(value) elif data_type == 'double': return double(value) elif data_type == 'float': return floating_point(value) elif data_type == 'long': return long_uint(value) elif data_type == 'longlong': return long_long_int(value) elif data_type == 'longstr': return long_str(value) elif data_type == 'octet': return octet(value) elif data_type == 'short': return short_uint(value) elif data_type == 'shortstr': return short_str(value) elif data_type == 'table': return field_table(value) elif data_type == 'timestamp': return timestamp(value) elif data_type == 'void': return None raise ValueError('Unknown type: {}'.format(data_type)) def _to_str(value): """Ensure the field table keys are strings (unicode or otherwise) :param bytes value: The value to try and decode to unicode :rtype: unicode or str """ if PYTHON3: return value.decode('utf-8') try: return str(value.decode('utf-8')) except UnicodeEncodeError: return value.decode('utf-8') # Define a data type mapping to methods METHODS = { 'array': field_array, 'bit': bit, 'boolean': boolean, 'byte_array': byte_array, 'decimal': decimal, 'double': double, 'float': floating_point, 'long': long_uint, 'longlong': long_long_int, 'longstr': long_str, 'octet': octet, 'short': short_uint, 'shortstr': short_str, 'table': field_table, 'timestamp': timestamp } pamqp-2.3.0/pamqp/encode.py000066400000000000000000000314731345615226700156020ustar00rootroot00000000000000# -*- encoding: utf-8 -*- """ AMQP Data Encoder ================= Functions for encoding data of various types including field tables and arrays """ import calendar import datetime import decimal as _decimal import logging import struct import time from pamqp import PYTHON3 LOGGER = logging.getLogger(__name__) if PYTHON3: long = int unicode = None # Dont throw exceptions as it is not defined DEPRECATED_RABBITMQ_SUPPORT = False """Toggle to support older versions of RabbitMQ.""" def support_deprecated_rabbitmq(): """Invoke to restrict the data types available in field-tables that are sent to RabbitMQ. """ global DEPRECATED_RABBITMQ_SUPPORT DEPRECATED_RABBITMQ_SUPPORT = True def bit(value, byte, position): """Encode a bit value :param int value: Value to decode :param int byte: The byte to apply the value to :param int position: The position in the byte to set the bit on :rtype: tuple of bytes used and a bool value """ return byte | (value << position) def boolean(value): """Encode a boolean value. :param bool value: Value to encode :rtype: bytes """ if not isinstance(value, bool): raise TypeError('bool type required') return struct.pack('>B', int(value)) def byte_array(value): """Encode a bytearray :param bytearray value: Value to encode :rtype: bytes """ if not isinstance(value, bytearray): raise TypeError('bytearray type required') elif PYTHON3: return struct.pack('>I', len(value)) + value return bytes(struct.pack('>I', len(value)) + value) def decimal(value): """Encode a decimal.Decimal value. :param decimal.Decimal value: Value to encode :rtype: bytes """ if not isinstance(value, _decimal.Decimal): raise TypeError('decimal.Decimal type required') tmp = '%s' % value if '.' in tmp: decimals = len(tmp.split('.')[-1]) value = value.normalize() raw = int(value * (_decimal.Decimal(10)**decimals)) return struct.pack('>Bi', decimals, raw) return struct.pack('>Bi', 0, int(value)) def double(value): """Encode a floating point value as a double :param float value: Value to encode :rtype: str """ if not isinstance(value, float): raise TypeError('float type required') return struct.pack('>d', value) def floating_point(value): """Encode a floating point value. :param float value: Value to encode :rtype: bytes """ if not isinstance(value, float): raise TypeError('float type required') return struct.pack('>f', value) def long_int(value): """Encode a long integer. :param int value: Value to encode :rtype: bytes """ if PYTHON3 and not isinstance(value, int): raise TypeError('int type required') elif not isinstance(value, int) and not isinstance(value, long): raise TypeError('long type required') elif not (-2147483648 <= value <= 2147483647): raise TypeError('Long integer range: -2147483648 to 2147483647') return struct.pack('>l', value) def long_uint(value): """Encode a long integer. :param int value: Value to encode :rtype: bytes """ if PYTHON3 and not isinstance(value, int): raise TypeError('int type required') elif not isinstance(value, int) and not isinstance(value, long): raise TypeError('long type required') elif not (0 <= value <= 4294967295): raise TypeError('Long unsigned-integer range: 0 to 4294967295') return struct.pack('>L', value) def long_long_int(value): """Encode a long-long int. :param long or int value: Value to encode :rtype: bytes """ if PYTHON3 and not isinstance(value, int): raise TypeError('int type required') elif not isinstance(value, long) and not isinstance(value, int): raise TypeError('int or long type required') elif not (-9223372036854775808 <= value <= 9223372036854775807): raise TypeError('long-long integer range: ' '-9223372036854775808 to 9223372036854775807') return struct.pack('>q', value) def long_string(value): """Encode a "long string" which the specific defines as any non-null data. We will auto-convert str and unicode to bytes but ignore bytes objects and place them opaquely. :param value: Value to encode :type value: bytes or str or unicode :rtype: bytes :raises: TypeError """ if PYTHON3 and not isinstance(value, (bytes, str)): raise TypeError('bytes or str required') elif not PYTHON3 and not isinstance(value, (bytes, str, unicode)): raise TypeError('bytes, str or unicode required') if not isinstance(value, bytes): value = _utf8_encode(value) return struct.pack('>I', len(value)) + value def octet(value): """Encode an octet value. :param value: Value to encode :rtype: bytes :raises: TypeError """ if not isinstance(value, int): raise TypeError('int type required') return struct.pack('B', value) def short_int(value): """Encode a short integer. :param int value: Value to encode :rtype: bytes :raises: TypeError """ if not isinstance(value, (int, long)): raise TypeError('int or long type required') elif not (-32768 <= value <= 32767): raise TypeError('Short integer range: -32678 to 32767') return struct.pack('>h', value) def short_uint(value): """Encode an unsigned short integer. :param int value: Value to encode :rtype: bytes :raises: TypeError """ if not isinstance(value, int): raise TypeError('int type required') elif not (0 <= value <= 65535): raise TypeError('Short unsigned integer range: 0 to 65535') return struct.pack('>H', value) def short_string(value): """ Encode a string. :param value: Value to encode :type value: bytes or str or unicode :rtype: bytes :raises: TypeError """ if PYTHON3 and not isinstance(value, (bytes, str)): raise TypeError('bytes or str required') elif not PYTHON3 and not isinstance(value, (bytes, str, unicode)): raise TypeError('bytes, str or unicode required') # Ensure that the value is utf-8 encoded if it's unicode value = _utf8_encode(value) return struct.pack('B', len(value)) + value def timestamp(value): """Encode a datetime.datetime object or time.struct_time. :param value: Value to encode :type value: datetime.datetime, time.struct_time, integer :rtype: bytes :raises: TypeError """ if isinstance(value, datetime.datetime): value = value.timetuple() elif isinstance(value, int): value = time.gmtime(value) if isinstance(value, time.struct_time): return struct.pack('>Q', calendar.timegm(value)) raise TypeError('datetime.datetime or time.struct_time type required') def field_array(value): """Encode a field array from a dictionary. :param list value: Value to encode :rtype: bytes :raises: TypeError """ if not isinstance(value, list): raise TypeError('list type required') data = [] for item in value: data.append(encode_table_value(item)) output = b''.join(data) return struct.pack('>I', len(output)) + output def field_table(value): """Encode a field table from a dictionary. :param dict or None value: Value to encode :rtype: bytes :raises: TypeError """ # If there is no value, return a standard 4 null bytes if not value: return struct.pack('>I', 0) elif not isinstance(value, dict): raise TypeError('dict type required, got {}'.format(type(value))) # Iterate through all of the keys and encode the data into a table data = [] for key, value in sorted(value.items()): # UTF-8 encode the key since it behaves like a short-string key = _utf8_encode(key) # According to the spec, field names should be 128 char max if len(key) > 128: LOGGER.warning('Truncating key %s to 128 bytes', key) key = key[0:128] # Append the field header / delimiter data.append(struct.pack('B', len(key))) data.append(key) try: data.append(encode_table_value(value)) except TypeError as err: raise TypeError('{} error: {}/'.format(key, err)) # Join all of the data together as a string output = b''.join(data) return struct.pack('>I', len(output)) + output def table_integer(value): """Determines the best type of numeric type to encode value as, preferring the smallest data size first. :param int value: Value to encode :rtype: bytes :raises: TypeError """ if DEPRECATED_RABBITMQ_SUPPORT: return _deprecated_table_integer(value) # Send the appropriately sized data value if 0 <= value <= 255: return b'b' + octet(value) elif -32768 <= value <= 32767: return b's' + short_int(value) elif 0 <= value <= 65535: return b'u' + short_uint(value) elif -2147483648 <= value <= 2147483647: return b'I' + long_int(value) elif 0 <= value <= 4294967295: return b'i' + long_uint(value) elif -9223372036854775808 <= value <= 9223372036854775807: return b'l' + long_long_int(value) raise TypeError('Unsupported numeric value: {}'.format(value)) def _deprecated_table_integer(value): """Determines the best type of numeric type to encode value as, preferring the smallest data size first, supporting versions of RabbitMQ < 3.6 :param int value: Value to encode :rtype: bytes :raises: TypeError """ # Send the appropriately sized data value if 0 <= value <= 255: return b'b' + octet(value) elif -32768 <= value <= 32767: return b's' + short_int(value) elif -2147483648 <= value <= 2147483647: return b'I' + long_int(value) elif -9223372036854775808 <= value <= 9223372036854775807: return b'l' + long_long_int(value) raise TypeError('Unsupported numeric value: {}'.format(value)) def encode_table_value(value): """Takes a value of any type and tries to encode it with the proper encoder :param any value: Value to encode :rtype: bytes :raises: TypeError """ # Determine the field type and encode it if isinstance(value, bool): result = b't' + boolean(value) elif isinstance(value, int) or isinstance(value, long): result = table_integer(value) elif isinstance(value, _decimal.Decimal): result = b'D' + decimal(value) elif isinstance(value, float): result = b'f' + floating_point(value) elif PYTHON3 and isinstance(value, (str, bytes)): result = b'S' + long_string(value) elif not PYTHON3 and isinstance(value, (str, bytes, unicode)): result = b'S' + long_string(value) elif (isinstance(value, datetime.datetime) or isinstance(value, time.struct_time)): result = b'T' + timestamp(value) elif isinstance(value, dict): result = b'F' + field_table(value) elif isinstance(value, list): result = b'A' + field_array(value) elif isinstance(value, bytearray): result = b'x' + byte_array(value) elif value is None: result = b'V' else: raise TypeError('Unknown type: {} ({!r})'.format(type(value), value)) # Return the encoded value return result def by_type(value, data_type): """Takes a value of any type and tries to encode it with the specified encoder. :param any value: Value to encode :param str data_type: type of data to encode :rtype: bytes :raises: TypeError """ # Determine the field type and encode it if data_type == 'field_array': return field_array(value) elif data_type == 'bytearray': return byte_array(value) elif data_type == 'double': return double(value) elif data_type == 'long': return long_uint(value) elif data_type == 'longlong': return long_long_int(value) elif data_type == 'longstr': return long_string(value) elif data_type == 'octet': return octet(value) elif data_type == 'short': return short_uint(value) elif data_type == 'shortstr': return short_string(value) elif data_type == 'table': return field_table(value) elif data_type == 'timestamp': return timestamp(value) elif data_type == 'void': return None raise TypeError('Unknown type: {}'.format(value)) def _utf8_encode(value): """Ensure that a string or unicode object is UTF-8 encoded. :param value: The value to evaluate :type value: str, bytes, or unicode :rtype: bytes """ if PYTHON3 and isinstance(value, str): return value.encode('utf-8') elif not PYTHON3 and isinstance(value, unicode): return value.encode('utf-8') return value pamqp-2.3.0/pamqp/exceptions.py000066400000000000000000000007151345615226700165210ustar00rootroot00000000000000# -*- encoding: utf-8 -*- """ pamqp specific exceptions that do not fit within the AMQP exceptions contained in pamqp.specification """ class PAMQPException(Exception): """Base exception for all pamqp specific exceptions""" class UnmarshalingException(PAMQPException): """Raised when a frame is not able to be unmarshaled.""" def __str__(self): return 'Could not unmarshal {} frame: {}'.format( self.args[0], self.args[1]) pamqp-2.3.0/pamqp/frame.py000066400000000000000000000174551345615226700154430ustar00rootroot00000000000000# -*- encoding: utf-8 -*- """Manage the marshaling and unmarshaling of AMQP frames unmarshal will turn a raw AMQP byte stream into the appropriate AMQP objects from the specification file. marshal will take an object created from the specification file and turn it into a raw byte stream. """ import logging import struct from pamqp import (body, decode, exceptions, header, heartbeat, PYTHON3, specification) AMQP = b'AMQP' FRAME_HEADER_SIZE = 7 FRAME_END_CHAR = chr(specification.FRAME_END) DECODE_FRAME_END_CHAR = FRAME_END_CHAR if PYTHON3: FRAME_END_CHAR = bytes((specification.FRAME_END, )) DECODE_FRAME_END_CHAR = specification.FRAME_END LOGGER = logging.getLogger(__name__) UNMARSHAL_FAILURE = 0, 0, None def unmarshal(data_in): """Takes in binary data and maps builds the appropriate frame type, returning a frame object. :param bytes data_in: Raw byte stream data :rtype: tuple of bytes consumed, channel, and a frame object :raises: specification.FrameError """ # Look to see if it's a protocol header frame try: frame_value = _unmarshal_protocol_header_frame(data_in) if frame_value: return 8, 0, frame_value except ValueError as error: raise exceptions.UnmarshalingException(header.ProtocolHeader, error) # Decode the low level frame and break it into parts frame_type, channel_id, frame_size = frame_parts(data_in) # Heartbeats do not have frame length indicators if frame_type == specification.FRAME_HEARTBEAT and frame_size == 0: return 8, channel_id, heartbeat.Heartbeat() if not frame_size: raise exceptions.UnmarshalingException('Unknown', 'No frame size') byte_count = FRAME_HEADER_SIZE + frame_size + 1 if byte_count > len(data_in): raise exceptions.UnmarshalingException('Unknown', 'Not all data received') if data_in[byte_count - 1] != DECODE_FRAME_END_CHAR: raise exceptions.UnmarshalingException('Unknown', 'Last byte error') frame_data = data_in[FRAME_HEADER_SIZE:byte_count - 1] # Decode a method frame if frame_type == specification.FRAME_METHOD: return byte_count, channel_id, _unmarshal_method_frame(frame_data) # Decode a header frame elif frame_type == specification.FRAME_HEADER: return byte_count, channel_id, _unmarshal_header_frame(frame_data) # Decode a body frame elif frame_type == specification.FRAME_BODY: return byte_count, channel_id, _unmarshal_body_frame(frame_data) raise exceptions.UnmarshalingException( 'Unknown', 'Unknown frame type: {}'.format(frame_type)) def marshal(frame_value, channel_id): """Marshal a frame to be sent over the wire. :param frame_value: The frame object to marshal :type frame_value: pamqp.specification.Frame or pamqp.heartbeat.Heartbeat :param int channel_id: The channel number to send the frame on :rtype: str :raises: ValueError """ if isinstance(frame_value, header.ProtocolHeader): return frame_value.marshal() elif isinstance(frame_value, specification.Frame): return _marshal_method_frame(frame_value, channel_id) elif isinstance(frame_value, header.ContentHeader): return _marshal_content_header_frame(frame_value, channel_id) elif isinstance(frame_value, body.ContentBody): return _marshal_content_body_frame(frame_value, channel_id) elif isinstance(frame_value, heartbeat.Heartbeat): return frame_value.marshal() raise ValueError('Could not determine frame type: {}'.format(frame_value)) def _unmarshal_protocol_header_frame(data_in): """Attempt to unmarshal a protocol header frame The ProtocolHeader is abbreviated in size and functionality compared to the rest of the frame types, so return UNMARSHAL_ERROR doesn't apply as cleanly since we don't have all of the attributes to return even regardless of success or failure. :param bytes data_in: Raw byte stream data :rtype: header.ProtocolHeader :raises: ValueError """ # Do the first four bytes match? if data_in[0:4] == AMQP: frame = header.ProtocolHeader() frame.unmarshal(data_in) return frame def _unmarshal_method_frame(frame_data): """Attempt to unmarshal a method frame :param bytes frame_data: Raw frame data to assign to our method frame :return tuple: Amount of data consumed and the frame object """ # Get the Method Index from the class data bytes_used, method_index = decode.long_int(frame_data[0:4]) # Create an instance of the method object we're going to unmarshal try: method = specification.INDEX_MAPPING[method_index]() except KeyError: raise exceptions.UnmarshalingException( 'Unknown', 'Unknown method index: {}'.format(str(method_index))) # Unmarshal the data try: method.unmarshal(frame_data[bytes_used:]) except struct.error as error: raise exceptions.UnmarshalingException(method, error) # Unmarshal the data in the object and return it return method def _unmarshal_header_frame(frame_data): """Attempt to unmarshal a header frame :param bytes frame_data: Raw frame data to assign to our header frame :return tuple: Amount of data consumed and the frame object """ content_header = header.ContentHeader() try: content_header.unmarshal(frame_data) except struct.error as error: raise exceptions.UnmarshalingException('ContentHeader', error) return content_header def _unmarshal_body_frame(frame_data): """Attempt to unmarshal a body frame :param bytes frame_data: Raw frame data to assign to our body frame :return tuple: Amount of data consumed and the frame object """ content_body = body.ContentBody() content_body.unmarshal(frame_data) return content_body def frame_parts(data_in): """Try and decode a low-level AMQP frame and return the parts of the frame. :param bytes data_in: Raw byte stream data :return tuple: frame type, channel number, and frame data to decode """ # Get the Frame Type, Channel Number and Frame Size try: return struct.unpack('>BHI', data_in[0:FRAME_HEADER_SIZE]) except struct.error: # We didn't get a full frame return UNMARSHAL_FAILURE def _marshal(frame_type, channel_id, payload): """Marshal the low-level AMQ frame. :param int frame_type: The frame type to marshal :param int channel_id: The channel it will be sent on :param bytes|bytes payload: The frame payload :rtype: str or bytes """ return b''.join([ struct.pack('>BHI', frame_type, channel_id, len(payload)), payload, FRAME_END_CHAR ]) def _marshal_content_body_frame(frame_value, channel_id): """Marshal as many content body frames as needed to transmit the content :param body.ContentBody frame_value: Frame object to marshal :param int channel_id: The channel number for the frame(s) :rtype: str """ return _marshal(specification.FRAME_BODY, channel_id, frame_value.marshal()) def _marshal_content_header_frame(frame_value, channel_id): """Marshal a content header frame :param header.ContentHeader frame_value: Frame object to marshal :param int channel_id: The channel number for the frame :rtype: str """ return _marshal(specification.FRAME_HEADER, channel_id, frame_value.marshal()) def _marshal_method_frame(frame_value, channel_id): """Marshal a method frame :param specification.Frame frame_value: Frame object to marshal :param int channel_id: The channel number for the frame :rtype: str """ return _marshal( specification.FRAME_METHOD, channel_id, struct.pack('>I', frame_value.index) + frame_value.marshal()) pamqp-2.3.0/pamqp/header.py000066400000000000000000000104661345615226700155740ustar00rootroot00000000000000# -*- encoding: utf-8 -*- """ AMQP Header Class Definitions For encoding AMQP Header frames into binary AMQP stream data and decoding AMQP binary data into AMQP Header frames. """ import struct from pamqp import decode, specification AMQP = b'AMQP' class ProtocolHeader(object): """Class that represents the AMQP Protocol Header""" name = 'ProtocolHeader' def __init__(self, major_version=None, minor_version=None, revision=None): """Construct a Protocol Header frame object for the specified AMQP version. :param int major_version: Major version number :param int minor_version: Minor version number :param int revision: Revision number """ self.major_version = major_version or specification.VERSION[0] self.minor_version = minor_version or specification.VERSION[1] self.revision = revision or specification.VERSION[2] def marshal(self): """Return the full AMQP wire protocol frame data representation of the ProtocolHeader frame. :rtype: str or bytes """ return AMQP + struct.pack('BBBB', 0, self.major_version, self.minor_version, self.revision) def unmarshal(self, data): """Dynamically decode the frame data applying the values to the method object by iterating through the attributes in order and decoding them. :param bytes data: The binary encoded method data :rtype: int byte count of data used to unmarshal the frame :raises: ValueError """ try: (self.major_version, self.minor_version, self.revision) = struct.unpack('BBB', data[5:8]) except struct.error: raise ValueError('Data did not match the ProtocolHeader ' 'format: {}'.format(data)) # All in we consume 8 bytes return 8 class ContentHeader(object): """Represent a content header frame A Content Header frame is received after a Basic.Deliver or Basic.GetOk frame and has the data and properties for the Content Body frames that follow. """ name = 'ContentHeader' def __init__(self, weight=0, body_size=0, properties=None): """Initialize the Exchange.DeleteOk class :param int weight: Unused, must be 0 :param long body_size: The size of the body for the message across all received AMQP frames :param specification.Basic.Properties properties: Message properties """ self.class_id = None self.weight = weight self.body_size = body_size self.properties = properties or specification.Basic.Properties() def marshal(self): """Return the AMQP binary encoded value of the frame """ return struct.pack('>HxxQ', specification.Basic.frame_id, self.body_size) + self.properties.marshal() def unmarshal(self, data): """Dynamically decode the frame data applying the values to the method object by iterating through the attributes in order and decoding them. :param bytes data: The binary encoded method data :rtype: int byte count of data used to unmarshal the frame :raises: ValueError """ # Get the class, weight and body size (self.class_id, self.weight, self.body_size) = struct.unpack('>HHQ', data[0:12]) # Get the flags for what properties we have available offset, flags = self._get_flags(data[12:]) # Demarshal the properties self.properties.unmarshal(flags, data[12 + offset:]) def _get_flags(self, data): """Decode the flags from the data returning the bytes consumed and flags :param bytes data: The data to pull flags out of :rtype: int, int """ # Defaults bytes_consumed, flags, flagword_index = 0, 0, 0 # Read until we don't have a value pulled out of the flags while True: consumed, partial_flags = decode.short_int(data) bytes_consumed += consumed flags |= (partial_flags << (flagword_index * 16)) if not partial_flags & 1: break flagword_index += 1 # Return the bytes consumed and the flags return bytes_consumed, flags pamqp-2.3.0/pamqp/heartbeat.py000066400000000000000000000013251345615226700162750ustar00rootroot00000000000000# -*- encoding: utf-8 -*- """ AMQP Heartbeat Frame, used to create new Heartbeat frames for sending to a peer """ import struct from pamqp import PYTHON3, specification class Heartbeat(object): """Heartbeat frame object mapping class. AMQP Heartbeat frames are mapped on to this class for a common access structure to the attributes/data values. """ name = 'Heartbeat' @staticmethod def marshal(): """Return the binary frame content :rtype: str or bytes """ value = struct.pack('>BHI', specification.FRAME_HEARTBEAT, 0, 0) if PYTHON3: return value + bytes((specification.FRAME_END, )) return value + chr(specification.FRAME_END) pamqp-2.3.0/pamqp/specification.py000066400000000000000000002527511345615226700171710ustar00rootroot00000000000000"""specification.py Auto-generated AMQP Support Module WARNING: DO NOT EDIT. To Generate run tools/codegen.py """ __since__ = '2019-04-18' import struct import warnings from pamqp import decode, encode # AMQP Protocol Version VERSION = (0, 9, 1) # RabbitMQ Defaults DEFAULT_HOST = 'localhost' DEFAULT_PORT = 5672 DEFAULT_USER = 'guest' DEFAULT_PASS = 'guest' DEFAULT_VHOST = '/' # AMQP Constants FRAME_METHOD = 1 FRAME_HEADER = 2 FRAME_BODY = 3 FRAME_HEARTBEAT = 8 FRAME_MIN_SIZE = 4096 FRAME_END = 206 # Indicates that the method completed successfully. This reply code is reserved # for future use - the current protocol design does not use positive # confirmation and reply codes are sent only in case of an error. REPLY_SUCCESS = 200 # Not included in the spec XML or JSON files. FRAME_MAX_SIZE = 131072 # AMQP data types DATA_TYPES = [ 'bit', 'long', 'longlong', 'longstr', 'octet', 'short', 'shortstr', 'table', 'timestamp' ] # AMQP domains DOMAINS = { 'channel-id': 'longstr', 'class-id': 'short', 'consumer-tag': 'shortstr', 'delivery-tag': 'longlong', 'destination': 'shortstr', 'duration': 'longlong', 'exchange-name': 'shortstr', 'method-id': 'short', 'no-ack': 'bit', 'no-local': 'bit', 'offset': 'longlong', 'path': 'shortstr', 'peer-properties': 'table', 'queue-name': 'shortstr', 'redelivered': 'bit', 'reference': 'longstr', 'reject-code': 'short', 'reject-text': 'shortstr', 'reply-code': 'short', 'reply-text': 'shortstr', 'security-token': 'longstr' } # Other constants DEPRECATION_WARNING = 'This command is deprecated in AMQP 0-9-1' class Frame(object): """Base Class for AMQP Methods which specifies the encoding and decoding behavior. """ __slots__ = [] frame_id = 0 index = 0 name = 'Frame' synchronous = False valid_responses = [] def __iter__(self): """Iterate the attributes and values as key, value pairs. :rtype: tuple """ for attribute in self.__slots__: yield (attribute, getattr(self, attribute)) def __contains__(self, item): """Return if the item is in the attribute list. :rtype: bool """ return item in self.__slots__ def __getitem__(self, item): """Return an attribute as if it were a dict. :param str item: The item to look for :raises: KeyError :rtype: any """ return getattr(self, item) def __len__(self): """Return the length of the attribute list. :rtype: int """ return len(self.__slots__) def __repr__(self): """Return the representation of the frame object :return: str """ return '<%s.%s object at %s>' % (__name__, self.name, hex(id(self))) @classmethod def type(cls, attr): """Return the data type for an attribute. :rtype: str """ return getattr(cls, '_' + attr) def marshal(self): """ Dynamically encode the frame by taking the list of attributes and encode them item by item getting the value form the object attribute and the data type from the class attribute. :rtype: str """ output = [] processing_bitset = False byte = None offset = 0 for argument in self.__slots__: data_type = self.type(argument) # Check if we need to turn on bit processing if not processing_bitset and data_type == 'bit': byte = 0 offset = 0 processing_bitset = True # Get the data value data_value = getattr(self, argument) # If we're processing a bitset, apply special rules if processing_bitset: # Is this value not a bit? turn off bitset processing and # append the byte value as an octet if data_type != 'bit': processing_bitset = False output.append(encode.octet(byte)) else: # Apply the bit value to the byte byte = encode.bit(data_value, byte, offset) offset += 1 if offset == 8: # We've filled a byte for all bits, add the byte output.append(encode.octet(byte)) # Turn off processing, we'll turn on in next iteration # if needed processing_bitset = False # Go to the next iteration continue # Not a bit, so just process by type output.append(encode.by_type(data_value, data_type)) # Append the last byte if we're processing a bitset if processing_bitset: output.append(encode.octet(byte)) return b''.join(output) def unmarshal(self, data): """ Dynamically decode the frame data applying the values to the method object by iterating through the attributes in order and decoding them. :param str data: The binary encoded method data """ offset = 0 processing_bitset = False for argument in self.__slots__: data_type = self.type(argument) if offset == 7 and processing_bitset: data = data[1:] offset = 0 if processing_bitset and data_type != 'bit': offset = 0 processing_bitset = False data = data[1:] consumed, value = decode.by_type(data, data_type, offset) if data_type == 'bit': offset += 1 processing_bitset = True consumed = 0 setattr(self, argument, value) if consumed: data = data[consumed:] class PropertiesBase(object): """Provide a base object that marshals and unmarshals the Basic.Properties object values. """ __slots__ = [] flags = {} name = 'PropertiesBase' def __contains__(self, item): return item in self.__slots__ def __delattr__(self, item): setattr(self, item, None) def __iter__(self): """Iterate the attributes and values as key, value pairs. :rtype: tuple """ for attribute in self.__slots__: yield (attribute, getattr(self, attribute)) @classmethod def attributes(cls): """Return the list of attributes :rtype: list """ return [attr for attr in cls.__slots__] @classmethod def type(cls, attr): """Return the data type for an attribute. :rtype: str """ return getattr(cls, '_' + attr) def encode_property(self, property_name, property_value): """Encode a single property value :param str property_name: The property name to encode :param any property_value: The value to encode """ return encode.by_type(property_value, self.type(property_name)) def marshal(self): """Take the Basic.Properties data structure and marshal it into the data structure needed for the ContentHeader. :rtype: bytes """ flags = 0 parts = [] for property_name in self.__slots__: property_value = getattr(self, property_name) if property_value is not None and property_value != '': flags = flags | self.flags[property_name] parts.append( self.encode_property(property_name, property_value)) flag_pieces = [] while True: remainder = flags >> 16 partial_flags = flags & 0xFFFE if remainder != 0: partial_flags |= 1 flag_pieces.append(struct.pack('>H', partial_flags)) flags = remainder if not flags: break return b''.join(flag_pieces + parts) def to_dict(self): """Return the properties as a dict :rtype: dict """ return dict(self) def unmarshal(self, flags, data): """ Dynamically decode the frame data applying the values to the method object by iterating through the attributes in order and decoding them. :param int flags: Flags that indicate if the data has the property :param bytes data: The binary encoded method data """ for property_name in self.__slots__: if flags & self.flags[property_name]: data_type = getattr(self.__class__, '_' + property_name) consumed, value = decode.by_type(data, data_type) setattr(self, property_name, value) data = data[consumed:] # AMQP Errors class AMQPContentTooLarge(Warning): """ The client attempted to transfer content larger than the server could accept at the present time. The client may retry at a later time. """ name = 'CONTENT-TOO-LARGE' value = 311 class AMQPNoRoute(Warning): """ Undocumented AMQP Soft Error """ name = 'NO-ROUTE' value = 312 class AMQPNoConsumers(Warning): """ When the exchange cannot deliver to a consumer when the immediate flag is set. As a result of pending data on the queue or the absence of any consumers of the queue. """ name = 'NO-CONSUMERS' value = 313 class AMQPAccessRefused(Warning): """ The client attempted to work with a server entity to which it has no access due to security settings. """ name = 'ACCESS-REFUSED' value = 403 class AMQPNotFound(Warning): """ The client attempted to work with a server entity that does not exist. """ name = 'NOT-FOUND' value = 404 class AMQPResourceLocked(Warning): """ The client attempted to work with a server entity to which it has no access because another client is working with it. """ name = 'RESOURCE-LOCKED' value = 405 class AMQPPreconditionFailed(Warning): """ The client requested a method that was not allowed because some precondition failed. """ name = 'PRECONDITION-FAILED' value = 406 class AMQPConnectionForced(Exception): """ An operator intervened to close the connection for some reason. The client may retry at some later date. """ name = 'CONNECTION-FORCED' value = 320 class AMQPInvalidPath(Exception): """ The client tried to work with an unknown virtual host. """ name = 'INVALID-PATH' value = 402 class AMQPFrameError(Exception): """ The sender sent a malformed frame that the recipient could not decode. This strongly implies a programming error in the sending peer. """ name = 'FRAME-ERROR' value = 501 class AMQPSyntaxError(Exception): """ The sender sent a frame that contained illegal values for one or more fields. This strongly implies a programming error in the sending peer. """ name = 'SYNTAX-ERROR' value = 502 class AMQPCommandInvalid(Exception): """ The client sent an invalid sequence of frames, attempting to perform an operation that was considered invalid by the server. This usually implies a programming error in the client. """ name = 'COMMAND-INVALID' value = 503 class AMQPChannelError(Exception): """ The client attempted to work with a channel that had not been correctly opened. This most likely indicates a fault in the client layer. """ name = 'CHANNEL-ERROR' value = 504 class AMQPUnexpectedFrame(Exception): """ The peer sent a frame that was not expected, usually in the context of a content header and body. This strongly indicates a fault in the peer's content processing. """ name = 'UNEXPECTED-FRAME' value = 505 class AMQPResourceError(Exception): """ The server could not complete the method because it lacked sufficient resources. This may be due to the client creating too many of some type of entity. """ name = 'RESOURCE-ERROR' value = 506 class AMQPNotAllowed(Exception): """ The client tried to work with some entity in a manner that is prohibited by the server, due to security settings or by some other criteria. """ name = 'NOT-ALLOWED' value = 530 class AMQPNotImplemented(Exception): """ The client tried to use functionality that is not implemented in the server. """ name = 'NOT-IMPLEMENTED' value = 540 class AMQPInternalError(Exception): """ The server could not complete the method because of an internal error. The server may require intervention by an operator in order to resume normal operations. """ name = 'INTERNAL-ERROR' value = 541 # AMQP Error code to class mapping ERRORS = { 320: AMQPConnectionForced, 505: AMQPUnexpectedFrame, 502: AMQPSyntaxError, 503: AMQPCommandInvalid, 530: AMQPNotAllowed, 504: AMQPChannelError, 402: AMQPInvalidPath, 403: AMQPAccessRefused, 404: AMQPNotFound, 405: AMQPResourceLocked, 406: AMQPPreconditionFailed, 311: AMQPContentTooLarge, 312: AMQPNoRoute, 313: AMQPNoConsumers, 506: AMQPResourceError, 540: AMQPNotImplemented, 541: AMQPInternalError, 501: AMQPFrameError } # AMQP Classes and Methods class Connection(object): """Work with socket connections The connection class provides methods for a client to establish a network connection to a server, and for both peers to operate the connection thereafter. """ __slots__ = [] # AMQP Class Number and Mapping Index frame_id = 10 index = 0x000A0000 class Start(Frame): """Start connection negotiation This method starts the connection negotiation process by telling the client the protocol version that the server proposes, along with a list of security mechanisms which the client can use for authentication. """ # AMQP Method Number and Mapping Index frame_id = 10 index = 0x000A000A name = 'Connection.Start' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Connection.StartOk'] # AMQP Method Attributes __slots__ = [ 'version_major', 'version_minor', 'server_properties', 'mechanisms', 'locales' ] # Class Attribute Types _version_major = 'octet' _version_minor = 'octet' _server_properties = 'table' _mechanisms = 'longstr' _locales = 'longstr' def __init__(self, version_major=0, version_minor=9, server_properties=None, mechanisms='PLAIN', locales='en_US'): """Initialize the Connection.Start class :param int version_major: Protocol major version :param int version_minor: Protocol minor version :param dict server_properties: Server properties :param str mechanisms: Available security mechanisms :param str locales: Available message locales """ # Protocol major version self.version_major = version_major # Protocol minor version self.version_minor = version_minor # Server properties self.server_properties = server_properties # Available security mechanisms self.mechanisms = mechanisms # Available message locales self.locales = locales class StartOk(Frame): """Select security mechanism and locale This method selects a SASL security mechanism. """ # AMQP Method Number and Mapping Index frame_id = 11 index = 0x000A000B name = 'Connection.StartOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['client_properties', 'mechanism', 'response', 'locale'] # Class Attribute Types _client_properties = 'table' _mechanism = 'shortstr' _response = 'longstr' _locale = 'shortstr' def __init__(self, client_properties=None, mechanism='PLAIN', response='', locale='en_US'): """Initialize the Connection.StartOk class :param dict client_properties: Client properties :param str mechanism: Selected security mechanism :param str response: Security response data :param str locale: Selected message locale """ # Client properties self.client_properties = client_properties # Selected security mechanism self.mechanism = mechanism # Security response data self.response = response # Selected message locale self.locale = locale class Secure(Frame): """Security mechanism challenge The SASL protocol works by exchanging challenges and responses until both peers have received sufficient information to authenticate each other. This method challenges the client to provide more information. """ # AMQP Method Number and Mapping Index frame_id = 20 index = 0x000A0014 name = 'Connection.Secure' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Connection.SecureOk'] # AMQP Method Attributes __slots__ = ['challenge'] # Class Attribute Types _challenge = 'longstr' def __init__(self, challenge=''): """Initialize the Connection.Secure class :param str challenge: Security challenge data """ # Security challenge data self.challenge = challenge class SecureOk(Frame): """Security mechanism response This method attempts to authenticate, passing a block of SASL data for the security mechanism at the server side. """ # AMQP Method Number and Mapping Index frame_id = 21 index = 0x000A0015 name = 'Connection.SecureOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['response'] # Class Attribute Types _response = 'longstr' def __init__(self, response=''): """Initialize the Connection.SecureOk class :param str response: Security response data """ # Security response data self.response = response class Tune(Frame): """Propose connection tuning parameters This method proposes a set of connection configuration values to the client. The client can accept and/or adjust these. """ # AMQP Method Number and Mapping Index frame_id = 30 index = 0x000A001E name = 'Connection.Tune' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Connection.TuneOk'] # AMQP Method Attributes __slots__ = ['channel_max', 'frame_max', 'heartbeat'] # Class Attribute Types _channel_max = 'short' _frame_max = 'long' _heartbeat = 'short' def __init__(self, channel_max=0, frame_max=0, heartbeat=0): """Initialize the Connection.Tune class :param int channel_max: Proposed maximum channels :param int/long frame_max: Proposed maximum frame size :param int heartbeat: Desired heartbeat delay """ # Proposed maximum channels self.channel_max = channel_max # Proposed maximum frame size self.frame_max = frame_max # Desired heartbeat delay self.heartbeat = heartbeat class TuneOk(Frame): """Negotiate connection tuning parameters This method sends the client's connection tuning parameters to the server. Certain fields are negotiated, others provide capability information. """ # AMQP Method Number and Mapping Index frame_id = 31 index = 0x000A001F name = 'Connection.TuneOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['channel_max', 'frame_max', 'heartbeat'] # Class Attribute Types _channel_max = 'short' _frame_max = 'long' _heartbeat = 'short' def __init__(self, channel_max=0, frame_max=0, heartbeat=0): """Initialize the Connection.TuneOk class :param int channel_max: Negotiated maximum channels :param int/long frame_max: Negotiated maximum frame size :param int heartbeat: Desired heartbeat delay """ # Negotiated maximum channels self.channel_max = channel_max # Negotiated maximum frame size self.frame_max = frame_max # Desired heartbeat delay self.heartbeat = heartbeat class Open(Frame): """Open connection to virtual host This method opens a connection to a virtual host, which is a collection of resources, and acts to separate multiple application domains within a server. The server may apply arbitrary limits per virtual host, such as the number of each type of entity that may be used, per connection and/or in total. """ # AMQP Method Number and Mapping Index frame_id = 40 index = 0x000A0028 name = 'Connection.Open' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Connection.OpenOk'] # AMQP Method Attributes __slots__ = ['virtual_host', 'capabilities', 'insist'] # Class Attribute Types _virtual_host = 'shortstr' _capabilities = 'shortstr' _insist = 'bit' def __init__(self, virtual_host='/', capabilities='', insist=False): """Initialize the Connection.Open class :param str virtual_host: Virtual host name :param str capabilities: Deprecated :param bool insist: Deprecated """ # Virtual host name self.virtual_host = virtual_host # Deprecated self.capabilities = capabilities # Deprecated self.insist = insist class OpenOk(Frame): """Signal that connection is ready This method signals to the client that the connection is ready for use. """ # AMQP Method Number and Mapping Index frame_id = 41 index = 0x000A0029 name = 'Connection.OpenOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['known_hosts'] # Class Attribute Types _known_hosts = 'shortstr' def __init__(self, known_hosts=''): """Initialize the Connection.OpenOk class :param str known_hosts: Deprecated """ # Deprecated self.known_hosts = known_hosts class Close(Frame): """Request a connection close This method indicates that the sender wants to close the connection. This may be due to internal conditions (e.g. a forced shut-down) or due to an error handling a specific method, i.e. an exception. When a close is due to an exception, the sender provides the class and method id of the method which caused the exception. """ # AMQP Method Number and Mapping Index frame_id = 50 index = 0x000A0032 name = 'Connection.Close' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Connection.CloseOk'] # AMQP Method Attributes __slots__ = ['reply_code', 'reply_text', 'class_id', 'method_id'] # Class Attribute Types _reply_code = 'short' _reply_text = 'shortstr' _class_id = 'short' _method_id = 'short' def __init__(self, reply_code=0, reply_text='', class_id=0, method_id=0): """Initialize the Connection.Close class :param int reply_code: Reply code from server :param str reply_text: Localised reply text :param int class_id: Failing method class :param int method_id: Failing method ID """ # Reply code from server self.reply_code = reply_code # Localised reply text self.reply_text = reply_text # Failing method class self.class_id = class_id # Failing method ID self.method_id = method_id class CloseOk(Frame): """Confirm a connection close This method confirms a Connection.Close method and tells the recipient that it is safe to release resources for the connection and close the socket. """ # AMQP Method Number and Mapping Index frame_id = 51 index = 0x000A0033 name = 'Connection.CloseOk' # Specifies if this is a synchronous AMQP method synchronous = False class Blocked(Frame): """Signal that connection is blocked This method signals to the client that the connection is blocked by RabbitMQ. """ # AMQP Method Number and Mapping Index frame_id = 60 index = 0x000A003C name = 'Connection.Blocked' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['reason'] # Class Attribute Types _reason = 'shortstr' def __init__(self, reason=''): """Initialize the Connection.Blocked class :param str reason: """ self.reason = reason class Unblocked(Frame): """Signal that connection is no longer blocked This method signals to the client that the connection is no longer blocked by RabbitMQ. """ # AMQP Method Number and Mapping Index frame_id = 61 index = 0x000A003D name = 'Connection.Unblocked' # Specifies if this is a synchronous AMQP method synchronous = False class Channel(object): """Work with channels The channel class provides methods for a client to establish a channel to a server and for both peers to operate the channel thereafter. """ __slots__ = [] # AMQP Class Number and Mapping Index frame_id = 20 index = 0x00140000 class Open(Frame): """Open a channel for use This method opens a channel to the server. """ # AMQP Method Number and Mapping Index frame_id = 10 index = 0x0014000A name = 'Channel.Open' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Channel.OpenOk'] # AMQP Method Attributes __slots__ = ['out_of_band'] # Class Attribute Types _out_of_band = 'shortstr' def __init__(self, out_of_band=''): """Initialize the Channel.Open class :param str out_of_band: Protocol level field, do not use, must be zero. """ # Protocol level field, do not use, must be zero. self.out_of_band = out_of_band class OpenOk(Frame): """Signal that the channel is ready This method signals to the client that the channel is ready for use. """ # AMQP Method Number and Mapping Index frame_id = 11 index = 0x0014000B name = 'Channel.OpenOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['channel_id'] # Class Attribute Types _channel_id = 'longstr' def __init__(self, channel_id=''): """Initialize the Channel.OpenOk class :param str channel_id: Deprecated """ # Deprecated self.channel_id = channel_id class Flow(Frame): """Enable/disable flow from peer This method asks the peer to pause or restart the flow of content data sent by a consumer. This is a simple flow-control mechanism that a peer can use to avoid overflowing its queues or otherwise finding itself receiving more messages than it can process. Note that this method is not intended for window control. It does not affect contents returned by Basic.Get-Ok methods. """ # AMQP Method Number and Mapping Index frame_id = 20 index = 0x00140014 name = 'Channel.Flow' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Channel.FlowOk'] # AMQP Method Attributes __slots__ = ['active'] # Class Attribute Types _active = 'bit' def __init__(self, active=None): """Initialize the Channel.Flow class :param bool active: Start/stop content frames """ # Start/stop content frames self.active = active class FlowOk(Frame): """Confirm a flow method Confirms to the peer that a flow command was received and processed. """ # AMQP Method Number and Mapping Index frame_id = 21 index = 0x00140015 name = 'Channel.FlowOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['active'] # Class Attribute Types _active = 'bit' def __init__(self, active=None): """Initialize the Channel.FlowOk class :param bool active: Current flow setting """ # Current flow setting self.active = active class Close(Frame): """Request a channel close This method indicates that the sender wants to close the channel. This may be due to internal conditions (e.g. a forced shut-down) or due to an error handling a specific method, i.e. an exception. When a close is due to an exception, the sender provides the class and method id of the method which caused the exception. """ # AMQP Method Number and Mapping Index frame_id = 40 index = 0x00140028 name = 'Channel.Close' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Channel.CloseOk'] # AMQP Method Attributes __slots__ = ['reply_code', 'reply_text', 'class_id', 'method_id'] # Class Attribute Types _reply_code = 'short' _reply_text = 'shortstr' _class_id = 'short' _method_id = 'short' def __init__(self, reply_code=0, reply_text='', class_id=0, method_id=0): """Initialize the Channel.Close class :param int reply_code: Reply code from server :param str reply_text: Localised reply text :param int class_id: Failing method class :param int method_id: Failing method ID """ # Reply code from server self.reply_code = reply_code # Localised reply text self.reply_text = reply_text # Failing method class self.class_id = class_id # Failing method ID self.method_id = method_id class CloseOk(Frame): """Confirm a channel close This method confirms a Channel.Close method and tells the recipient that it is safe to release resources for the channel. """ # AMQP Method Number and Mapping Index frame_id = 41 index = 0x00140029 name = 'Channel.CloseOk' # Specifies if this is a synchronous AMQP method synchronous = False class Exchange(object): """Work with exchanges Exchanges match and distribute messages across queues. Exchanges can be configured in the server or declared at runtime. """ __slots__ = [] # AMQP Class Number and Mapping Index frame_id = 40 index = 0x00280000 class Declare(Frame): """Verify exchange exists, create if needed This method creates an exchange if it does not already exist, and if the exchange exists, verifies that it is of the correct and expected class. """ # AMQP Method Number and Mapping Index frame_id = 10 index = 0x0028000A name = 'Exchange.Declare' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Exchange.DeclareOk'] # AMQP Method Attributes __slots__ = [ 'ticket', 'exchange', 'exchange_type', 'passive', 'durable', 'auto_delete', 'internal', 'nowait', 'arguments' ] # Class Attribute Types _ticket = 'short' _exchange = 'shortstr' _exchange_type = 'shortstr' _passive = 'bit' _durable = 'bit' _auto_delete = 'bit' _internal = 'bit' _nowait = 'bit' _arguments = 'table' def __init__(self, ticket=0, exchange='', exchange_type='direct', passive=False, durable=False, auto_delete=False, internal=False, nowait=False, arguments=None): """Initialize the Exchange.Declare class Note that the AMQP type argument is referred to as "exchange_type" to not conflict with the Python type keyword. :param int ticket: Deprecated :param str exchange: :param str exchange_type: Exchange type :param bool passive: Do not create exchange :param bool durable: Request a durable exchange :param bool auto_delete: Automatically delete when not in use :param bool internal: Deprecated :param bool nowait: Do not send a reply method :param dict arguments: Arguments for declaration """ # Deprecated self.ticket = ticket self.exchange = exchange # Exchange type self.exchange_type = exchange_type # Do not create exchange self.passive = passive # Request a durable exchange self.durable = durable # Automatically delete when not in use self.auto_delete = auto_delete # Deprecated self.internal = internal # Do not send a reply method self.nowait = nowait # Arguments for declaration self.arguments = arguments or {} class DeclareOk(Frame): """Confirm exchange declaration This method confirms a Declare method and confirms the name of the exchange, essential for automatically-named exchanges. """ # AMQP Method Number and Mapping Index frame_id = 11 index = 0x0028000B name = 'Exchange.DeclareOk' # Specifies if this is a synchronous AMQP method synchronous = False class Delete(Frame): """Delete an exchange This method deletes an exchange. When an exchange is deleted all queue bindings on the exchange are cancelled. """ # AMQP Method Number and Mapping Index frame_id = 20 index = 0x00280014 name = 'Exchange.Delete' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Exchange.DeleteOk'] # AMQP Method Attributes __slots__ = ['ticket', 'exchange', 'if_unused', 'nowait'] # Class Attribute Types _ticket = 'short' _exchange = 'shortstr' _if_unused = 'bit' _nowait = 'bit' def __init__(self, ticket=0, exchange='', if_unused=False, nowait=False): """Initialize the Exchange.Delete class :param int ticket: Deprecated :param str exchange: :param bool if_unused: Delete only if unused :param bool nowait: Do not send a reply method """ # Deprecated self.ticket = ticket self.exchange = exchange # Delete only if unused self.if_unused = if_unused # Do not send a reply method self.nowait = nowait class DeleteOk(Frame): """Confirm deletion of an exchange This method confirms the deletion of an exchange. """ # AMQP Method Number and Mapping Index frame_id = 21 index = 0x00280015 name = 'Exchange.DeleteOk' # Specifies if this is a synchronous AMQP method synchronous = False class Bind(Frame): # AMQP Method Number and Mapping Index frame_id = 30 index = 0x0028001E name = 'Exchange.Bind' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Exchange.BindOk'] # AMQP Method Attributes __slots__ = [ 'ticket', 'destination', 'source', 'routing_key', 'nowait', 'arguments' ] # Class Attribute Types _ticket = 'short' _destination = 'shortstr' _source = 'shortstr' _routing_key = 'shortstr' _nowait = 'bit' _arguments = 'table' def __init__(self, ticket=0, destination='', source='', routing_key='', nowait=False, arguments=None): """Initialize the Exchange.Bind class :param int ticket: Deprecated :param str destination: :param str source: :param str routing-key: :param bool nowait: Do not send a reply method :param dict arguments: """ # Deprecated self.ticket = ticket self.destination = destination self.source = source self.routing_key = routing_key # Do not send a reply method self.nowait = nowait self.arguments = arguments or {} class BindOk(Frame): # AMQP Method Number and Mapping Index frame_id = 31 index = 0x0028001F name = 'Exchange.BindOk' # Specifies if this is a synchronous AMQP method synchronous = False class Unbind(Frame): # AMQP Method Number and Mapping Index frame_id = 40 index = 0x00280028 name = 'Exchange.Unbind' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Exchange.UnbindOk'] # AMQP Method Attributes __slots__ = [ 'ticket', 'destination', 'source', 'routing_key', 'nowait', 'arguments' ] # Class Attribute Types _ticket = 'short' _destination = 'shortstr' _source = 'shortstr' _routing_key = 'shortstr' _nowait = 'bit' _arguments = 'table' def __init__(self, ticket=0, destination='', source='', routing_key='', nowait=False, arguments=None): """Initialize the Exchange.Unbind class :param int ticket: Deprecated :param str destination: :param str source: :param str routing-key: :param bool nowait: Do not send a reply method :param dict arguments: """ # Deprecated self.ticket = ticket self.destination = destination self.source = source self.routing_key = routing_key # Do not send a reply method self.nowait = nowait self.arguments = arguments or {} class UnbindOk(Frame): # AMQP Method Number and Mapping Index frame_id = 51 index = 0x00280033 name = 'Exchange.UnbindOk' # Specifies if this is a synchronous AMQP method synchronous = False class Queue(object): """Work with queues Queues store and forward messages. Queues can be configured in the server or created at runtime. Queues must be attached to at least one exchange in order to receive messages from publishers. """ __slots__ = [] # AMQP Class Number and Mapping Index frame_id = 50 index = 0x00320000 class Declare(Frame): """Declare queue, create if needed This method creates or checks a queue. When creating a new queue the client can specify various properties that control the durability of the queue and its contents, and the level of sharing for the queue. """ # AMQP Method Number and Mapping Index frame_id = 10 index = 0x0032000A name = 'Queue.Declare' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Queue.DeclareOk'] # AMQP Method Attributes __slots__ = [ 'ticket', 'queue', 'passive', 'durable', 'exclusive', 'auto_delete', 'nowait', 'arguments' ] # Class Attribute Types _ticket = 'short' _queue = 'shortstr' _passive = 'bit' _durable = 'bit' _exclusive = 'bit' _auto_delete = 'bit' _nowait = 'bit' _arguments = 'table' def __init__(self, ticket=0, queue='', passive=False, durable=False, exclusive=False, auto_delete=False, nowait=False, arguments=None): """Initialize the Queue.Declare class :param int ticket: Deprecated :param str queue: :param bool passive: Do not create queue :param bool durable: Request a durable queue :param bool exclusive: Request an exclusive queue :param bool auto_delete: Auto-delete queue when unused :param bool nowait: Do not send a reply method :param dict arguments: Arguments for declaration """ # Deprecated self.ticket = ticket self.queue = queue # Do not create queue self.passive = passive # Request a durable queue self.durable = durable # Request an exclusive queue self.exclusive = exclusive # Auto-delete queue when unused self.auto_delete = auto_delete # Do not send a reply method self.nowait = nowait # Arguments for declaration self.arguments = arguments or {} class DeclareOk(Frame): """Confirms a queue definition This method confirms a Declare method and confirms the name of the queue, essential for automatically-named queues. """ # AMQP Method Number and Mapping Index frame_id = 11 index = 0x0032000B name = 'Queue.DeclareOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['queue', 'message_count', 'consumer_count'] # Class Attribute Types _queue = 'shortstr' _message_count = 'long' _consumer_count = 'long' def __init__(self, queue='', message_count=0, consumer_count=0): """Initialize the Queue.DeclareOk class :param str queue: :param int/long message_count: Number of messages in queue :param int/long consumer_count: Number of consumers """ self.queue = queue # Number of messages in queue self.message_count = message_count # Number of consumers self.consumer_count = consumer_count class Bind(Frame): """Bind queue to an exchange This method binds a queue to an exchange. Until a queue is bound it will not receive any messages. In a classic messaging model, store-and- forward queues are bound to a direct exchange and subscription queues are bound to a topic exchange. """ # AMQP Method Number and Mapping Index frame_id = 20 index = 0x00320014 name = 'Queue.Bind' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Queue.BindOk'] # AMQP Method Attributes __slots__ = [ 'ticket', 'queue', 'exchange', 'routing_key', 'nowait', 'arguments' ] # Class Attribute Types _ticket = 'short' _queue = 'shortstr' _exchange = 'shortstr' _routing_key = 'shortstr' _nowait = 'bit' _arguments = 'table' def __init__(self, ticket=0, queue='', exchange='', routing_key='', nowait=False, arguments=None): """Initialize the Queue.Bind class :param int ticket: Deprecated :param str queue: :param str exchange: Name of the exchange to bind to :param str routing_key: Message routing key :param bool nowait: Do not send a reply method :param dict arguments: Arguments for binding """ # Deprecated self.ticket = ticket self.queue = queue # Name of the exchange to bind to self.exchange = exchange # Message routing key self.routing_key = routing_key # Do not send a reply method self.nowait = nowait # Arguments for binding self.arguments = arguments or {} class BindOk(Frame): """Confirm bind successful This method confirms that the bind was successful. """ # AMQP Method Number and Mapping Index frame_id = 21 index = 0x00320015 name = 'Queue.BindOk' # Specifies if this is a synchronous AMQP method synchronous = False class Purge(Frame): """Purge a queue This method removes all messages from a queue which are not awaiting acknowledgment. """ # AMQP Method Number and Mapping Index frame_id = 30 index = 0x0032001E name = 'Queue.Purge' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Queue.PurgeOk'] # AMQP Method Attributes __slots__ = ['ticket', 'queue', 'nowait'] # Class Attribute Types _ticket = 'short' _queue = 'shortstr' _nowait = 'bit' def __init__(self, ticket=0, queue='', nowait=False): """Initialize the Queue.Purge class :param int ticket: Deprecated :param str queue: :param bool nowait: Do not send a reply method """ # Deprecated self.ticket = ticket self.queue = queue # Do not send a reply method self.nowait = nowait class PurgeOk(Frame): """Confirms a queue purge This method confirms the purge of a queue. """ # AMQP Method Number and Mapping Index frame_id = 31 index = 0x0032001F name = 'Queue.PurgeOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['message_count'] # Class Attribute Types _message_count = 'long' def __init__(self, message_count=0): """Initialize the Queue.PurgeOk class :param int/long message-count: """ self.message_count = message_count class Delete(Frame): """Delete a queue This method deletes a queue. When a queue is deleted any pending messages are sent to a dead-letter queue if this is defined in the server configuration, and all consumers on the queue are cancelled. """ # AMQP Method Number and Mapping Index frame_id = 40 index = 0x00320028 name = 'Queue.Delete' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Queue.DeleteOk'] # AMQP Method Attributes __slots__ = ['ticket', 'queue', 'if_unused', 'if_empty', 'nowait'] # Class Attribute Types _ticket = 'short' _queue = 'shortstr' _if_unused = 'bit' _if_empty = 'bit' _nowait = 'bit' def __init__(self, ticket=0, queue='', if_unused=False, if_empty=False, nowait=False): """Initialize the Queue.Delete class :param int ticket: Deprecated :param str queue: :param bool if_unused: Delete only if unused :param bool if_empty: Delete only if empty :param bool nowait: Do not send a reply method """ # Deprecated self.ticket = ticket self.queue = queue # Delete only if unused self.if_unused = if_unused # Delete only if empty self.if_empty = if_empty # Do not send a reply method self.nowait = nowait class DeleteOk(Frame): """Confirm deletion of a queue This method confirms the deletion of a queue. """ # AMQP Method Number and Mapping Index frame_id = 41 index = 0x00320029 name = 'Queue.DeleteOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['message_count'] # Class Attribute Types _message_count = 'long' def __init__(self, message_count=0): """Initialize the Queue.DeleteOk class :param int/long message-count: """ self.message_count = message_count class Unbind(Frame): """Unbind a queue from an exchange This method unbinds a queue from an exchange. """ # AMQP Method Number and Mapping Index frame_id = 50 index = 0x00320032 name = 'Queue.Unbind' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Queue.UnbindOk'] # AMQP Method Attributes __slots__ = ['ticket', 'queue', 'exchange', 'routing_key', 'arguments'] # Class Attribute Types _ticket = 'short' _queue = 'shortstr' _exchange = 'shortstr' _routing_key = 'shortstr' _arguments = 'table' def __init__(self, ticket=0, queue='', exchange='', routing_key='', arguments=None): """Initialize the Queue.Unbind class :param int ticket: Deprecated :param str queue: :param str exchange: :param str routing_key: Routing key of binding :param dict arguments: Arguments of binding """ # Deprecated self.ticket = ticket self.queue = queue self.exchange = exchange # Routing key of binding self.routing_key = routing_key # Arguments of binding self.arguments = arguments or {} class UnbindOk(Frame): """Confirm unbind successful This method confirms that the unbind was successful. """ # AMQP Method Number and Mapping Index frame_id = 51 index = 0x00320033 name = 'Queue.UnbindOk' # Specifies if this is a synchronous AMQP method synchronous = False class Basic(object): """Work with basic content The Basic class provides methods that support an industry-standard messaging model. """ __slots__ = [] # AMQP Class Number and Mapping Index frame_id = 60 index = 0x003C0000 class Qos(Frame): """Specify quality of service This method requests a specific quality of service. The QoS can be specified for the current channel or for all channels on the connection. The particular properties and semantics of a qos method always depend on the content class semantics. Though the qos method could in principle apply to both peers, it is currently meaningful only for the server. """ # AMQP Method Number and Mapping Index frame_id = 10 index = 0x003C000A name = 'Basic.Qos' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Basic.QosOk'] # AMQP Method Attributes __slots__ = ['prefetch_size', 'prefetch_count', 'global_'] # Class Attribute Types _prefetch_size = 'long' _prefetch_count = 'short' _global_ = 'bit' def __init__(self, prefetch_size=0, prefetch_count=0, global_=False): """Initialize the Basic.Qos class :param int/long prefetch_size: Prefetch window in octets :param int prefetch_count: Prefetch window in messages :param bool global_: Apply to entire connection """ # Prefetch window in octets self.prefetch_size = prefetch_size # Prefetch window in messages self.prefetch_count = prefetch_count # Apply to entire connection self.global_ = global_ class QosOk(Frame): """Confirm the requested qos This method tells the client that the requested QoS levels could be handled by the server. The requested QoS applies to all active consumers until a new QoS is defined. """ # AMQP Method Number and Mapping Index frame_id = 11 index = 0x003C000B name = 'Basic.QosOk' # Specifies if this is a synchronous AMQP method synchronous = False class Consume(Frame): """Start a queue consumer This method asks the server to start a "consumer", which is a transient request for messages from a specific queue. Consumers last as long as the channel they were declared on, or until the client cancels them. """ # AMQP Method Number and Mapping Index frame_id = 20 index = 0x003C0014 name = 'Basic.Consume' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Basic.ConsumeOk'] # AMQP Method Attributes __slots__ = [ 'ticket', 'queue', 'consumer_tag', 'no_local', 'no_ack', 'exclusive', 'nowait', 'arguments' ] # Class Attribute Types _ticket = 'short' _queue = 'shortstr' _consumer_tag = 'shortstr' _no_local = 'bit' _no_ack = 'bit' _exclusive = 'bit' _nowait = 'bit' _arguments = 'table' def __init__(self, ticket=0, queue='', consumer_tag='', no_local=False, no_ack=False, exclusive=False, nowait=False, arguments=None): """Initialize the Basic.Consume class :param int ticket: Deprecated :param str queue: :param str consumer-tag: :param bool no_local: Do not deliver own messages :param bool no_ack: No acknowledgement needed :param bool exclusive: Request exclusive access :param bool nowait: Do not send a reply method :param dict arguments: Arguments for declaration """ # Deprecated self.ticket = ticket self.queue = queue self.consumer_tag = consumer_tag # Do not deliver own messages self.no_local = no_local # No acknowledgement needed self.no_ack = no_ack # Request exclusive access self.exclusive = exclusive # Do not send a reply method self.nowait = nowait # Arguments for declaration self.arguments = arguments or {} class ConsumeOk(Frame): """Confirm a new consumer The server provides the client with a consumer tag, which is used by the client for methods called on the consumer at a later stage. """ # AMQP Method Number and Mapping Index frame_id = 21 index = 0x003C0015 name = 'Basic.ConsumeOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['consumer_tag'] # Class Attribute Types _consumer_tag = 'shortstr' def __init__(self, consumer_tag=''): """Initialize the Basic.ConsumeOk class :param str consumer-tag: """ self.consumer_tag = consumer_tag class Cancel(Frame): """End a queue consumer This method cancels a consumer. This does not affect already delivered messages, but it does mean the server will not send any more messages for that consumer. The client may receive an arbitrary number of messages in between sending the cancel method and receiving the cancel- ok reply. """ # AMQP Method Number and Mapping Index frame_id = 30 index = 0x003C001E name = 'Basic.Cancel' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Basic.CancelOk'] # AMQP Method Attributes __slots__ = ['consumer_tag', 'nowait'] # Class Attribute Types _consumer_tag = 'shortstr' _nowait = 'bit' def __init__(self, consumer_tag='', nowait=False): """Initialize the Basic.Cancel class :param str consumer_tag: Consumer tag :param bool nowait: Do not send a reply method """ # Consumer tag self.consumer_tag = consumer_tag # Do not send a reply method self.nowait = nowait class CancelOk(Frame): """Confirm a cancelled consumer This method confirms that the cancellation was completed. """ # AMQP Method Number and Mapping Index frame_id = 31 index = 0x003C001F name = 'Basic.CancelOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['consumer_tag'] # Class Attribute Types _consumer_tag = 'shortstr' def __init__(self, consumer_tag=''): """Initialize the Basic.CancelOk class :param str consumer_tag: Consumer tag """ # Consumer tag self.consumer_tag = consumer_tag class Publish(Frame): """Publish a message This method publishes a message to a specific exchange. The message will be routed to queues as defined by the exchange configuration and distributed to any active consumers when the transaction, if any, is committed. """ # AMQP Method Number and Mapping Index frame_id = 40 index = 0x003C0028 name = 'Basic.Publish' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = [ 'ticket', 'exchange', 'routing_key', 'mandatory', 'immediate' ] # Class Attribute Types _ticket = 'short' _exchange = 'shortstr' _routing_key = 'shortstr' _mandatory = 'bit' _immediate = 'bit' def __init__(self, ticket=0, exchange='', routing_key='', mandatory=False, immediate=False): """Initialize the Basic.Publish class :param int ticket: Deprecated :param str exchange: :param str routing_key: Message routing key :param bool mandatory: Indicate mandatory routing :param bool immediate: Request immediate delivery """ # Deprecated self.ticket = ticket self.exchange = exchange # Message routing key self.routing_key = routing_key # Indicate mandatory routing self.mandatory = mandatory # Request immediate delivery self.immediate = immediate class Return(Frame): """Return a failed message This method returns an undeliverable message that was published with the "immediate" flag set, or an unroutable message published with the "mandatory" flag set. The reply code and text provide information about the reason that the message was undeliverable. """ # AMQP Method Number and Mapping Index frame_id = 50 index = 0x003C0032 name = 'Basic.Return' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['reply_code', 'reply_text', 'exchange', 'routing_key'] # Class Attribute Types _reply_code = 'short' _reply_text = 'shortstr' _exchange = 'shortstr' _routing_key = 'shortstr' def __init__(self, reply_code=0, reply_text='', exchange='', routing_key=''): """Initialize the Basic.Return class :param int reply_code: Reply code from server :param str reply_text: Localised reply text :param str exchange: :param str routing_key: Message routing key """ # Reply code from server self.reply_code = reply_code # Localised reply text self.reply_text = reply_text self.exchange = exchange # Message routing key self.routing_key = routing_key class Deliver(Frame): """Notify the client of a consumer message This method delivers a message to the client, via a consumer. In the asynchronous message delivery model, the client starts a consumer using the Consume method, then the server responds with Deliver methods as and when messages arrive for that consumer. """ # AMQP Method Number and Mapping Index frame_id = 60 index = 0x003C003C name = 'Basic.Deliver' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = [ 'consumer_tag', 'delivery_tag', 'redelivered', 'exchange', 'routing_key' ] # Class Attribute Types _consumer_tag = 'shortstr' _delivery_tag = 'longlong' _redelivered = 'bit' _exchange = 'shortstr' _routing_key = 'shortstr' def __init__(self, consumer_tag='', delivery_tag=None, redelivered=False, exchange='', routing_key=''): """Initialize the Basic.Deliver class :param str consumer_tag: Consumer tag :param int/long delivery_tag: Server-assigned delivery tag :param bool redelivered: Message is being redelivered :param str exchange: :param str routing_key: Message routing key """ # Consumer tag self.consumer_tag = consumer_tag # Server-assigned delivery tag self.delivery_tag = delivery_tag # Message is being redelivered self.redelivered = redelivered self.exchange = exchange # Message routing key self.routing_key = routing_key class Get(Frame): """Direct access to a queue This method provides a direct access to the messages in a queue using a synchronous dialogue that is designed for specific types of application where synchronous functionality is more important than performance. """ # AMQP Method Number and Mapping Index frame_id = 70 index = 0x003C0046 name = 'Basic.Get' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Basic.GetOk', 'Basic.GetEmpty'] # AMQP Method Attributes __slots__ = ['ticket', 'queue', 'no_ack'] # Class Attribute Types _ticket = 'short' _queue = 'shortstr' _no_ack = 'bit' def __init__(self, ticket=0, queue='', no_ack=False): """Initialize the Basic.Get class :param int ticket: Deprecated :param str queue: :param bool no_ack: No acknowledgement needed """ # Deprecated self.ticket = ticket self.queue = queue # No acknowledgement needed self.no_ack = no_ack class GetOk(Frame): """Provide client with a message This method delivers a message to the client following a get method. A message delivered by 'get-ok' must be acknowledged unless the no-ack option was set in the get method. """ # AMQP Method Number and Mapping Index frame_id = 71 index = 0x003C0047 name = 'Basic.GetOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = [ 'delivery_tag', 'redelivered', 'exchange', 'routing_key', 'message_count' ] # Class Attribute Types _delivery_tag = 'longlong' _redelivered = 'bit' _exchange = 'shortstr' _routing_key = 'shortstr' _message_count = 'long' def __init__(self, delivery_tag=None, redelivered=False, exchange='', routing_key='', message_count=0): """Initialize the Basic.GetOk class :param int/long delivery_tag: Server-assigned delivery tag :param bool redelivered: Message is being redelivered :param str exchange: :param str routing_key: Message routing key :param int/long message_count: Number of messages in queue """ # Server-assigned delivery tag self.delivery_tag = delivery_tag # Message is being redelivered self.redelivered = redelivered self.exchange = exchange # Message routing key self.routing_key = routing_key # Number of messages in queue self.message_count = message_count class GetEmpty(Frame): """Indicate no messages available This method tells the client that the queue has no messages available for the client. """ # AMQP Method Number and Mapping Index frame_id = 72 index = 0x003C0048 name = 'Basic.GetEmpty' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['cluster_id'] # Class Attribute Types _cluster_id = 'shortstr' def __init__(self, cluster_id=''): """Initialize the Basic.GetEmpty class :param str cluster_id: Deprecated """ # Deprecated self.cluster_id = cluster_id class Ack(Frame): """Acknowledge one or more messages This method acknowledges one or more messages delivered via the Deliver or Get-Ok methods. The client can ask to confirm a single message or a set of messages up to and including a specific message. """ # AMQP Method Number and Mapping Index frame_id = 80 index = 0x003C0050 name = 'Basic.Ack' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['delivery_tag', 'multiple'] # Class Attribute Types _delivery_tag = 'longlong' _multiple = 'bit' def __init__(self, delivery_tag=0, multiple=False): """Initialize the Basic.Ack class :param int/long delivery_tag: Server-assigned delivery tag :param bool multiple: Acknowledge multiple messages """ # Server-assigned delivery tag self.delivery_tag = delivery_tag # Acknowledge multiple messages self.multiple = multiple class Reject(Frame): """Reject an incoming message This method allows a client to reject a message. It can be used to interrupt and cancel large incoming messages, or return untreatable messages to their original queue. """ # AMQP Method Number and Mapping Index frame_id = 90 index = 0x003C005A name = 'Basic.Reject' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['delivery_tag', 'requeue'] # Class Attribute Types _delivery_tag = 'longlong' _requeue = 'bit' def __init__(self, delivery_tag=None, requeue=True): """Initialize the Basic.Reject class :param int/long delivery_tag: Server-assigned delivery tag :param bool requeue: Requeue the message """ # Server-assigned delivery tag self.delivery_tag = delivery_tag # Requeue the message self.requeue = requeue class RecoverAsync(Frame): """Redeliver unacknowledged messages This method asks the server to redeliver all unacknowledged messages on a specified channel. Zero or more messages may be redelivered. This method is deprecated in favour of the synchronous Recover/Recover-Ok. """ # AMQP Method Number and Mapping Index frame_id = 100 index = 0x003C0064 name = 'Basic.RecoverAsync' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['requeue'] # Class Attribute Types _requeue = 'bit' def __init__(self, requeue=False): """Initialize the Basic.RecoverAsync class :param bool requeue: Requeue the message .. deprecated:: 0-9-1 This command is deprecated in AMQP 0-9-1 """ # Requeue the message self.requeue = requeue # This command is deprecated in AMQP 0-9-1 warnings.warn(DEPRECATION_WARNING, category=DeprecationWarning) class Recover(Frame): """Redeliver unacknowledged messages This method asks the server to redeliver all unacknowledged messages on a specified channel. Zero or more messages may be redelivered. This method replaces the asynchronous Recover. """ # AMQP Method Number and Mapping Index frame_id = 110 index = 0x003C006E name = 'Basic.Recover' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Basic.RecoverOk'] # AMQP Method Attributes __slots__ = ['requeue'] # Class Attribute Types _requeue = 'bit' def __init__(self, requeue=False): """Initialize the Basic.Recover class :param bool requeue: Requeue the message """ # Requeue the message self.requeue = requeue class RecoverOk(Frame): """Confirm recovery This method acknowledges a Basic.Recover method. """ # AMQP Method Number and Mapping Index frame_id = 111 index = 0x003C006F name = 'Basic.RecoverOk' # Specifies if this is a synchronous AMQP method synchronous = False class Nack(Frame): # AMQP Method Number and Mapping Index frame_id = 120 index = 0x003C0078 name = 'Basic.Nack' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Method Attributes __slots__ = ['delivery_tag', 'multiple', 'requeue'] # Class Attribute Types _delivery_tag = 'longlong' _multiple = 'bit' _requeue = 'bit' def __init__(self, delivery_tag=0, multiple=False, requeue=True): """Initialize the Basic.Nack class :param int/long delivery_tag: Server-assigned delivery tag :param bool multiple: :param bool requeue: """ # Server-assigned delivery tag self.delivery_tag = delivery_tag self.multiple = multiple self.requeue = requeue class Properties(PropertiesBase): """Content Properties""" name = 'Basic.Properties' __slots__ = [ 'content_type', 'content_encoding', 'headers', 'delivery_mode', 'priority', 'correlation_id', 'reply_to', 'expiration', 'message_id', 'timestamp', 'message_type', 'user_id', 'app_id', 'cluster_id' ] # Flag Values flags = { 'content_type': 32768, 'content_encoding': 16384, 'headers': 8192, 'delivery_mode': 4096, 'priority': 2048, 'correlation_id': 1024, 'reply_to': 512, 'expiration': 256, 'message_id': 128, 'timestamp': 64, 'message_type': 32, 'user_id': 16, 'app_id': 8, 'cluster_id': 4 } # Class Attribute Types _content_type = 'shortstr' _content_encoding = 'shortstr' _headers = 'table' _delivery_mode = 'octet' _priority = 'octet' _correlation_id = 'shortstr' _reply_to = 'shortstr' _expiration = 'shortstr' _message_id = 'shortstr' _timestamp = 'timestamp' _message_type = 'shortstr' _user_id = 'shortstr' _app_id = 'shortstr' _cluster_id = 'shortstr' frame_id = 60 index = 0x003C def __init__(self, content_type='', content_encoding='', headers=None, delivery_mode=None, priority=None, correlation_id='', reply_to='', expiration='', message_id='', timestamp=None, message_type='', user_id='', app_id='', cluster_id=''): """Initialize the Basic.Properties class Note that the AMQP property type is named message_type as to not conflict with the Python type keyword :param str content_type: MIME content type :param str content_encoding: MIME content encoding :param dict headers: Message header field table :param int delivery_mode: Non-persistent (1) or persistent (2) :param int priority: Message priority, 0 to 9 :param str correlation_id: Application correlation identifier :param str reply_to: Address to reply to :param str expiration: Message expiration specification :param str message_id: Application message identifier :param struct_time timestamp: Message timestamp :param str message_type: Message type name :param str user_id: Creating user id :param str app_id: Creating application id :param str cluster_id: Deprecated """ # MIME content type self.content_type = content_type # MIME content encoding self.content_encoding = content_encoding # Message header field table self.headers = headers # Non-persistent (1) or persistent (2) self.delivery_mode = delivery_mode # Message priority, 0 to 9 self.priority = priority # Application correlation identifier self.correlation_id = correlation_id # Address to reply to self.reply_to = reply_to # Message expiration specification self.expiration = expiration # Application message identifier self.message_id = message_id # Message timestamp self.timestamp = timestamp # Message type name self.message_type = message_type # Creating user id self.user_id = user_id # Creating application id self.app_id = app_id # Deprecated self.cluster_id = cluster_id class Tx(object): """Work with transactions The Tx class allows publish and ack operations to be batched into atomic units of work. The intention is that all publish and ack requests issued within a transaction will complete successfully or none of them will. Servers SHOULD implement atomic transactions at least where all publish or ack requests affect a single queue. Transactions that cover multiple queues may be non-atomic, given that queues can be created and destroyed asynchronously, and such events do not form part of any transaction. Further, the behaviour of transactions with respect to the immediate and mandatory flags on Basic.Publish methods is not defined. """ __slots__ = [] # AMQP Class Number and Mapping Index frame_id = 90 index = 0x005A0000 class Select(Frame): """Select standard transaction mode This method sets the channel to use standard transactions. The client must use this method at least once on a channel before using the Commit or Rollback methods. """ # AMQP Method Number and Mapping Index frame_id = 10 index = 0x005A000A name = 'Tx.Select' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Tx.SelectOk'] class SelectOk(Frame): """Confirm transaction mode This method confirms to the client that the channel was successfully set to use standard transactions. """ # AMQP Method Number and Mapping Index frame_id = 11 index = 0x005A000B name = 'Tx.SelectOk' # Specifies if this is a synchronous AMQP method synchronous = False class Commit(Frame): """Commit the current transaction This method commits all message publications and acknowledgments performed in the current transaction. A new transaction starts immediately after a commit. """ # AMQP Method Number and Mapping Index frame_id = 20 index = 0x005A0014 name = 'Tx.Commit' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Tx.CommitOk'] class CommitOk(Frame): """Confirm a successful commit This method confirms to the client that the commit succeeded. Note that if a commit fails, the server raises a channel exception. """ # AMQP Method Number and Mapping Index frame_id = 21 index = 0x005A0015 name = 'Tx.CommitOk' # Specifies if this is a synchronous AMQP method synchronous = False class Rollback(Frame): """Abandon the current transaction This method abandons all message publications and acknowledgments performed in the current transaction. A new transaction starts immediately after a rollback. Note that unacked messages will not be automatically redelivered by rollback; if that is required an explicit recover call should be issued. """ # AMQP Method Number and Mapping Index frame_id = 30 index = 0x005A001E name = 'Tx.Rollback' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Tx.RollbackOk'] class RollbackOk(Frame): """Confirm successful rollback This method confirms to the client that the rollback succeeded. Note that if an rollback fails, the server raises a channel exception. """ # AMQP Method Number and Mapping Index frame_id = 31 index = 0x005A001F name = 'Tx.RollbackOk' # Specifies if this is a synchronous AMQP method synchronous = False class Confirm(object): __slots__ = [] # AMQP Class Number and Mapping Index frame_id = 85 index = 0x00550000 class Select(Frame): # AMQP Method Number and Mapping Index frame_id = 10 index = 0x0055000A name = 'Confirm.Select' # Specifies if this is a synchronous AMQP method synchronous = True # Valid responses to this method valid_responses = ['Confirm.SelectOk'] # AMQP Method Attributes __slots__ = ['nowait'] # Class Attribute Types _nowait = 'bit' def __init__(self, nowait=False): """Initialize the Confirm.Select class :param bool nowait: Do not send a reply method """ # Do not send a reply method self.nowait = nowait class SelectOk(Frame): # AMQP Method Number and Mapping Index frame_id = 11 index = 0x0055000B name = 'Confirm.SelectOk' # Specifies if this is a synchronous AMQP method synchronous = False # AMQP Class.Method Index Mapping INDEX_MAPPING = { 0x000A000A: Connection.Start, 0x000A000B: Connection.StartOk, 0x000A0014: Connection.Secure, 0x000A0015: Connection.SecureOk, 0x000A001E: Connection.Tune, 0x000A001F: Connection.TuneOk, 0x000A0028: Connection.Open, 0x000A0029: Connection.OpenOk, 0x000A0032: Connection.Close, 0x000A0033: Connection.CloseOk, 0x000A003C: Connection.Blocked, 0x000A003D: Connection.Unblocked, 0x0014000A: Channel.Open, 0x0014000B: Channel.OpenOk, 0x00140014: Channel.Flow, 0x00140015: Channel.FlowOk, 0x00140028: Channel.Close, 0x00140029: Channel.CloseOk, 0x0028000A: Exchange.Declare, 0x0028000B: Exchange.DeclareOk, 0x00280014: Exchange.Delete, 0x00280015: Exchange.DeleteOk, 0x0028001E: Exchange.Bind, 0x0028001F: Exchange.BindOk, 0x00280028: Exchange.Unbind, 0x00280033: Exchange.UnbindOk, 0x0032000A: Queue.Declare, 0x0032000B: Queue.DeclareOk, 0x00320014: Queue.Bind, 0x00320015: Queue.BindOk, 0x0032001E: Queue.Purge, 0x0032001F: Queue.PurgeOk, 0x00320028: Queue.Delete, 0x00320029: Queue.DeleteOk, 0x00320032: Queue.Unbind, 0x00320033: Queue.UnbindOk, 0x003C000A: Basic.Qos, 0x003C000B: Basic.QosOk, 0x003C0014: Basic.Consume, 0x003C0015: Basic.ConsumeOk, 0x003C001E: Basic.Cancel, 0x003C001F: Basic.CancelOk, 0x003C0028: Basic.Publish, 0x003C0032: Basic.Return, 0x003C003C: Basic.Deliver, 0x003C0046: Basic.Get, 0x003C0047: Basic.GetOk, 0x003C0048: Basic.GetEmpty, 0x003C0050: Basic.Ack, 0x003C005A: Basic.Reject, 0x003C0064: Basic.RecoverAsync, 0x003C006E: Basic.Recover, 0x003C006F: Basic.RecoverOk, 0x003C0078: Basic.Nack, 0x005A000A: Tx.Select, 0x005A000B: Tx.SelectOk, 0x005A0014: Tx.Commit, 0x005A0015: Tx.CommitOk, 0x005A001E: Tx.Rollback, 0x005A001F: Tx.RollbackOk, 0x0055000A: Confirm.Select, 0x0055000B: Confirm.SelectOk } pamqp-2.3.0/requirements.txt000066400000000000000000000002571345615226700161350ustar00rootroot00000000000000codecov coverage flake8 flake8-comprehensions flake8-deprecated flake8-html flake8-import-order flake8-quotes flake8-rst-docstrings flake8-tuple lxml mock nose unittest2 yapf pamqp-2.3.0/setup.cfg000066400000000000000000000005711345615226700144710ustar00rootroot00000000000000[wheel] universal=1 [nosetests] cover-branches=1 cover-html=true cover-html-dir=coverage cover-package=pamqp cover-xml=true cover-xml-file=coverage.xml logging-level=DEBUG verbosity=2 with-coverage=1 with-xunit=true xunit-file=xunit.xml [flake8] application-import-names=pamqp ignore=RST303,RST399,W504,F821 exclude=bin,build,codegen,docs,env,env2.7 import-order-style=googlepamqp-2.3.0/setup.py000066400000000000000000000022731345615226700143630ustar00rootroot00000000000000import setuptools from pamqp import __version__ setuptools.setup( name='pamqp', version=__version__, description='RabbitMQ Focused AMQP low-level library', long_description=open('README.rst').read(), author='Gavin M. Roy', author_email='gavinmroy@gmail.com', url='http://pamqp.readthedocs.org', package_data={'': ['LICENSE', 'README.rst']}, packages=['pamqp', 'pamqp.codec'], extras_require={'codegen': ['lxml']}, license='BSD', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Topic :: Communications', 'Topic :: Internet', 'Topic :: Software Development :: Libraries' ], zip_safe=True) pamqp-2.3.0/tests/000077500000000000000000000000001345615226700140075ustar00rootroot00000000000000pamqp-2.3.0/tests/test_decoding.py000066400000000000000000000720171345615226700172030ustar00rootroot00000000000000# -*- encoding: utf-8 -*- import decimal import struct import time import unittest from pamqp import decode, PYTHON3 if PYTHON3: long = int unicode = None basestring = (bytes, str) PLATFORM_32BIT = (struct.calcsize('P') * 8) == 32 PLATFORM_64BIT = (struct.calcsize('P') * 8) == 64 def _utf8_key(value): return value.decode('utf-8') if not PYTHON3 else value class CodecDecodeTests(unittest.TestCase): FIELD_ARR = (b'\x00\x00\x00@s\x00\x01I\x00\x00\xaf\xc8S\x00\x00' b'\x00\x08Test \xe2\x9c\x88T\x00\x00\x00\x00Ec)\x92' b'I\xbb\x9a\xca\x00D\x02\x00\x00\x01:f@H\xf5\xc3l' b'\x00\x00\x00\x00\xc4e5\xffl\x80\x00\x00\x00\x00' b'\x00\x00\x08') FIELD_ARR_VALUE = [ 1, 45000, b'Test \xe2\x9c\x88', time.struct_time((2006, 11, 21, 16, 30, 10, 1, 325, 0)), -1147483648, decimal.Decimal('3.14'), 3.14, 3294967295, -9223372036854775800 ] FIELD_TBL = ( b'\x00\x00\x00\x9d\x08arrayvalA\x00\x00\x00\ts\x00\x01s\x00\x02s\x00' b'\x03\x07boolvalt\x01\x06decvalD\x02\x00\x00\x01:\x07dictvalF\x00' b'\x00\x00\r\x04f\xe2\x9c\x89S\x00\x00\x00\x03\xe2\x9c\x90\x08' b'floatvalf@H\xf5\xc3\x06intvals\x00\x01\x07longvalI6e&U\x06strvalS' b'\x00\x00\x00\x08Test \xe2\x9c\x88\x0ctimestampvalT\x00\x00\x00' b'\x00Ec)\x92\x04\xf0\x9f\x90\xb0V' ) FIELD_TBL_VALUE = { 'intval': 1, 'strval': b'Test \xe2\x9c\x88', 'boolval': True, 'timestampval': time.struct_time( (2006, 11, 21, 16, 30, 10, 1, 325, 0)), 'decval': decimal.Decimal('3.14'), _utf8_key('🐰'): None, 'floatval': 3.14, 'longval': long(912598613), 'dictval': { _utf8_key('f✉'): b'\xe2\x9c\x90' }, 'arrayval': [1, 2, 3] } def test_decode_by_type_invalid_data_type(self): self.assertRaises(ValueError, decode.by_type, b'Z\x00', b'foobar') def test_decode_bit_bytes_consumed(self): self.assertEqual(decode.bit(b'\xff', 4)[0], 0) def test_decode_invalid_value(self): self.assertRaises(ValueError, decode.bit, b'\xff', None) def test_decode_bit_on(self): self.assertTrue(decode.bit(b'\xff', 4)[1]) def test_decode_bit_off(self): self.assertFalse(decode.bit(b'\x0f', 4)[1]) def test_decode_boolean_bytes_consumed(self): self.assertEqual(decode.boolean(b'\x01')[0], 1) def test_decode_boolean_false(self): self.assertFalse(decode.boolean(b'\x00')[1]) def test_decode_boolean_false_data_type(self): self.assertIsInstance(decode.boolean(b'\x00')[1], bool) def test_decode_boolean_invalid_value(self): self.assertRaises(ValueError, decode.boolean, None) def test_decode_boolean_true(self): self.assertTrue(decode.boolean(b'\x01')[1]) def test_decode_boolean_true_data_type(self): self.assertIsInstance(decode.boolean(b'\x01')[1], bool) def test_decode_byte_array(self): self.assertEqual(decode.byte_array(b'\x00\x00\x00\x03ABC'), (7, bytearray([65, 66, 67]))) def test_decode_byte_array_invalid_value(self): self.assertRaises(ValueError, decode.byte_array, None) def test_decode_decimal_value_bytes_consumed(self): value = b'\x05\x00\x04\xcb/' self.assertEqual(decode.decimal(value)[0], len(value)) def test_decode_decimal_value_data_type(self): value = b'\x05\x00\x04\xcb/' self.assertIsInstance(decode.decimal(value)[1], decimal.Decimal) def test_decode_decimal_value(self): value = b'\x05\x00\x04\xcb/' self.assertEqual(round(float(decode.decimal(value)[1]), 5), round(float(decimal.Decimal('3.14159')), 5)) def test_decode_decimal_invalid_value(self): self.assertRaises(ValueError, decode.decimal, False) def test_decode_double_value(self): value = b'@\t!\xf9\xf0\x1b\x86n' self.assertEqual(round(decode.double(value)[1], 5), round(float(3.14159), 5)) def test_decode_double_invalid_value(self): self.assertRaises(ValueError, decode.double, 123) def test_decode_embedded_value_null(self): self.assertEqual(decode._embedded_value(b'\00')[1], None) def test_decode_embedded_value_invalid_data(self): self.assertRaises(ValueError, decode._embedded_value, b'Z\x00') def test_decode_floating_point_bytes_consumed(self): value = b'@I\x0f\xd0' self.assertEqual(decode.floating_point(value)[0], 4) def test_decode_floating_point_data_type(self): value = b'@I\x0f\xd0' self.assertIsInstance(decode.floating_point(value)[1], float) def test_decode_floating_point_invalid_value(self): self.assertRaises(ValueError, decode.floating_point, False) def test_decode_floating_point_value(self): value = b'@I\x0f\xd0' self.assertEqual(round(decode.floating_point(value)[1], 5), round(float(3.14159), 5)) def test_decode_long_int_bytes_consumed(self): value = b'\x7f\xff\xff\xff' self.assertEqual(decode.long_int(value)[0], 4) def test_decode_long_int_data_type(self): value = b'\x7f\xff\xff\xff' self.assertIsInstance(decode.long_int(value)[1], int) def test_decode_long_int_invalid_value(self): self.assertRaises(ValueError, decode.long_int, None) def test_decode_long_int_value(self): value = b'\x7f\xff\xff\xff' self.assertEqual(decode.long_int(value)[1], 2147483647) def test_decode_long_long_int_bytes_consumed(self): value = b'\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertEqual(decode.long_long_int(value)[0], 8) @unittest.skipIf(PLATFORM_32BIT, 'Skipped on 32-bit platforms') def test_decode_long_long_int_data_type_64bit(self): value = b'\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertIsInstance(decode.long_long_int(value)[1], int) @unittest.skipIf(PLATFORM_64BIT, 'Skipped on 64-bit platforms') def test_decode_long_long_int_data_type_32bit(self): value = b'\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertIsInstance(decode.long_long_int(value)[1], long) def test_decode_long_long_int_invalid_value(self): self.assertRaises(ValueError, decode.long_long_int, None) def test_decode_long_long_int_value(self): value = b'\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertEqual(decode.long_long_int(value)[1], 9223372036854775800) def test_decode_long_str_bytes_consumed(self): value = b'\x00\x00\x00\n0123456789' self.assertEqual(decode.long_str(value)[0], 14) def test_decode_long_str_data_type(self): value = b'\x00\x00\x00\n0123456789' self.assertIsInstance(decode.long_str(value)[1], basestring) def test_decode_long_str_data_type_unicode(self): self.assertIsInstance( decode.long_str(b'\x00\x00\x00\x0c\xd8\xa7' b'\xd8\xae\xd8\xaa\xd8\xa8' b'\xd8\xa7\xd8\xb1')[1], bytes) def test_decode_long_str_invalid_value(self): self.assertRaises(ValueError, decode.long_str, None) def test_decode_long_str_value(self): value = b'\x00\x00\x00\n0123456789' self.assertEqual(decode.long_str(value)[1], b'0123456789') def test_decode_octet_bytes_consumed(self): value = b'\xff' self.assertEqual(decode.octet(value)[0], 1) def test_decode_octet_data_type(self): value = b'\xff' self.assertIsInstance(decode.octet(value)[1], int) def test_decode_octet_invalid_value(self): self.assertRaises(ValueError, decode.octet, None) def test_decode_octet_value(self): value = b'\xff' self.assertEqual(decode.octet(value)[1], 255) def test_decode_short_int_bytes_consumed(self): value = b'\x7f\xff' self.assertEqual(decode.short_int(value)[0], 2) def test_decode_short_int_data_type(self): value = b'\x7f\xff' self.assertIsInstance(decode.short_int(value)[0], int) def test_decode_short_int_invalid_value(self): self.assertRaises(ValueError, decode.short_int, None) def test_decode_short_int_value(self): value = b'\x7f\xff' self.assertEqual(decode.short_int(value)[1], 32767) def test_decode_short_short_int_data_type(self): self.assertIsInstance(decode.short_short_int(b'\xff')[0], int) def test_decode_short_short_int_invalid_value(self): self.assertRaises(ValueError, decode.short_short_int, None) def test_decode_short_short_int_value(self): self.assertEqual(decode.short_short_int(b'\xff')[1], 255) def test_decode_short_str_bytes_consumed(self): self.assertEqual(decode.short_str(b'\n0123456789')[0], 11) def test_decode_short_str_data_type(self): self.assertIsInstance(decode.short_str(b'\n0123456789')[1], basestring) def test_decode_short_str_invalid_value(self): self.assertRaises(ValueError, decode.short_str, None) def test_decode_short_str_value(self): self.assertEqual(decode.short_str(b'\n0123456789')[1], '0123456789') def test_decode_timestamp_bytes_consumed(self): self.assertEqual(decode.timestamp(b'\x00\x00\x00\x00Ec)\x92')[0], 8) def test_decode_timestamp_data_type(self): self.assertIsInstance( decode.timestamp(b'\x00\x00\x00\x00Ec)\x92')[1], time.struct_time) def test_decode_timestamp_invalid_value(self): self.assertRaises(ValueError, decode.timestamp, None) def test_decode_timestamp_value(self): self.assertEqual( decode.timestamp(b'\x00\x00\x00\x00Ec)\x92')[1], time.struct_time((2006, 11, 21, 16, 30, 10, 1, 325, 0))) def test_decode_field_array_bytes_consumed(self): self.assertEqual( decode.field_array(self.FIELD_ARR)[0], len(self.FIELD_ARR)) def test_decode_field_array_data_type(self): self.assertIsInstance(decode.field_array(self.FIELD_ARR)[1], list) def test_decode_field_array_invalid_value(self): self.assertRaises(ValueError, decode.field_array, None) def test_decode_field_array_value(self): value = decode.field_array(self.FIELD_ARR)[1] for position in range(0, len(value)): if isinstance(value[position], float): self.assertAlmostEqual( round(value[position], 3), round(self.FIELD_ARR_VALUE[position], 3)) else: self.assertEqual(value[position], self.FIELD_ARR_VALUE[position]) def test_decode_field_table_bytes_consumed(self): self.assertEqual( decode.field_table(self.FIELD_TBL)[0], len(self.FIELD_TBL)) def test_decode_field_table_data_type(self): self.assertIsInstance(decode.field_table(self.FIELD_TBL)[1], dict) def test_decode_field_table_invalid_value(self): self.assertRaises(ValueError, decode.field_table, None) def test_decode_field_table_value(self): value = decode.field_table(self.FIELD_TBL)[1] for key in self.FIELD_TBL_VALUE.keys(): if isinstance(value[key], float): self.assertAlmostEqual(round(value[key], 3), round(self.FIELD_TBL_VALUE[key], 3)) else: self.assertEqual(value[key], self.FIELD_TBL_VALUE[key]) def test_decode_by_type_bit_bytes_consumed(self): self.assertEqual(decode.by_type(b'\xff', 'bit', 4)[0], 0) def test_decode_by_type_invalid_value(self): self.assertRaises(ValueError, decode.by_type, b'\xff', 'bit', None) def test_decode_by_type_bit_on(self): self.assertTrue(decode.by_type(b'\xff', 'bit', 4)[1]) def test_decode_by_type_bit_off(self): self.assertFalse(decode.by_type(b'\x0f', 'bit', 4)[1]) def test_decode_by_type_boolean_bytes_consumed(self): self.assertEqual(decode.by_type(b'\x01', 'boolean')[0], 1) def test_decode_by_type_boolean_false(self): self.assertFalse(decode.by_type(b'\x00', 'boolean')[1]) def test_decode_by_type_boolean_false_data_type(self): self.assertIsInstance(decode.by_type(b'\x00', 'boolean')[1], bool) def test_decode_by_type_boolean_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'boolean') def test_decode_by_type_boolean_true(self): self.assertTrue(decode.by_type(b'\x01', 'boolean')[1]) def test_decode_by_type_boolean_true_data_type(self): self.assertIsInstance(decode.by_type(b'\x01', 'boolean')[1], bool) def test_decode_by_type_byte_array_bytes_consumed(self): value = b'\x00\x00\x00\t123456789' self.assertEqual(decode.by_type(value, 'byte_array')[0], 13) def test_decode_by_type_byte_array_data_type(self): value = b'\x00\x00\x00\t123456789' self.assertIsInstance( decode.by_type(value, 'byte_array')[1], bytearray) def test_decode_by_type_byte_array_value(self): value = b'\x00\x00\x00\t123456789' self.assertEqual( decode.by_type(value, 'byte_array')[1], bytearray(b'123456789')) def test_decode_by_type_decimal_bytes_consumed(self): value = b'\x05\x00\x04\xcb/' self.assertEqual(decode.by_type(value, 'decimal')[0], len(value)) def test_decode_by_type_decimal_data_type(self): self.assertIsInstance( decode.by_type(b'\x05\x00\x04\xcb/', 'decimal')[1], decimal.Decimal) def test_decode_by_type_decimal_value(self): self.assertEqual( round(float(decode.by_type(b'\x05\x00\x04\xcb/', 'decimal')[1]), 5), round(float(decimal.Decimal('3.14159')), 5)) def test_decode_by_type_decimal_invalid_value(self): self.assertRaises(ValueError, decode.by_type, False, 'decimal') def test_decode_by_type_double_data_type(self): value = b'C\x0f\xd8\x91\x14\xb9\xc3\x98' self.assertIsInstance(decode.by_type(value, 'double')[1], float) def test_decode_by_type_double_bytes_consumed(self): value = b'C\x0f\xd8\x91\x14\xb9\xc3\x98' self.assertEqual(decode.by_type(value, 'double')[0], 8) def test_decode_by_type_double_value(self): value = b'C\x0f\xd8\x91\x14\xb9\xc3\x98' self.assertEqual( decode.by_type(value, 'double')[1], 1120480238450803.0) def test_decode_by_type_floating_point_data_type(self): self.assertIsInstance(decode.by_type(b'@I\x0f\xd0', 'float')[1], float) def test_decode_by_type_float_bytes_consumed(self): self.assertEqual(decode.by_type(b'@I\x0f\xd0', 'float')[0], 4) def test_decode_by_type_floating_point_invalid_value(self): self.assertRaises(ValueError, decode.by_type, False, 'float') def test_decode_by_type_floating_point_value(self): value = b'@I\x0f\xd0' self.assertEqual(round(decode.by_type(value, 'float')[1], 5), round(float(3.14159), 5)) def test_decode_by_type_long_bytes_consumed(self): value = b'\x7f\xff\xff\xff' self.assertEqual(decode.by_type(value, 'long')[0], 4) def test_decode_by_type_long_data_type(self): value = b'\x7f\xff\xff\xff' self.assertIsInstance(decode.by_type(value, 'long')[1], int) def test_decode_by_type_long_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'long') def test_decode_by_type_long_value(self): value = b'\x7f\xff\xff\xff' self.assertEqual(decode.by_type(value, 'long')[1], 2147483647) def test_decode_by_type_long_long_bytes_consumed(self): value = b'\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertEqual(decode.by_type(value, 'longlong')[0], 8) @unittest.skipIf(PLATFORM_64BIT, 'Skipped on 64-bit platforms') def test_decode_by_type_long_long_data_type_32bit(self): value = b'\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertIsInstance(decode.by_type(value, 'longlong')[1], long) @unittest.skipIf(PLATFORM_32BIT, 'Skipped on 32-bit platforms') def test_decode_by_type_long_long_data_type_64bit(self): value = b'\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertIsInstance(decode.by_type(value, 'longlong')[1], int) def test_decode_by_type_long_long_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'longlong') def test_decode_by_type_long_long_value(self): value = b'\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertEqual( decode.by_type(value, 'longlong')[1], 9223372036854775800) def test_decode_by_type_longstr_bytes_consumed(self): value = b'\x00\x00\x00\n0123456789' self.assertEqual(decode.by_type(value, 'longstr')[0], 14) def test_decode_by_type_longstr_data_type_with_unicode(self): value = b'\x00\x00\x00\x08Test \xe2\x9c\x88' self.assertIsInstance(decode.by_type(value, 'longstr')[1], bytes) def test_decode_by_type_longstr_data_type(self): value = b'\x00\x00\x00\n0123456789' self.assertIsInstance(decode.by_type(value, 'longstr')[1], basestring) def test_decode_by_type_longstr_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'longstr') def test_decode_by_type_longstr_value(self): value = b'\x00\x00\x00\n0123456789' self.assertEqual(decode.by_type(value, 'longstr')[1], b'0123456789') def test_decode_by_type_octet_bytes_consumed(self): self.assertEqual(decode.by_type(b'\xff', 'octet')[0], 1) def test_decode_by_type_octet_data_type(self): self.assertIsInstance(decode.by_type(b'\xff', 'octet')[1], int) def test_decode_by_type_octet_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'octet') def test_decode_by_type_octet_value(self): self.assertEqual(decode.by_type(b'\xff', 'octet')[1], 255) def test_decode_by_type_short_bytes_consumed(self): value = b'\x7f\xff' self.assertEqual(decode.by_type(value, 'short')[0], 2) def test_decode_by_type_short_data_type(self): value = b'\x7f\xff' self.assertIsInstance(decode.by_type(value, 'short')[1], int) def test_decode_by_type_short_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'short') def test_decode_by_type_short_value(self): value = b'\x7f\xff' self.assertEqual(decode.by_type(value, 'short')[1], 32767) def test_decode_by_type_timestamp_bytes_consumed(self): value = b'\x00\x00\x00\x00Ec)\x92' self.assertEqual(decode.by_type(value, 'timestamp')[0], 8) def test_decode_by_type_timestamp_data_type(self): value = b'\x00\x00\x00\x00Ec)\x92' self.assertIsInstance( decode.by_type(value, 'timestamp')[1], time.struct_time) def test_decode_by_type_timestamp_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'timestamp') def test_decode_by_type_timestamp_value(self): value = b'\x00\x00\x00\x00Ec)\x92' self.assertEqual( decode.by_type(value, 'timestamp')[1], time.struct_time((2006, 11, 21, 16, 30, 10, 1, 325, 0))) def test_decode_by_type_void(self): self.assertIsNone(decode.by_type(b'', 'void')) def test_decode_by_type_field_array_bytes_consumed(self): self.assertEqual( decode.by_type(self.FIELD_ARR, 'array')[0], len(self.FIELD_ARR)) def test_decode_by_type_field_array_data_type(self): self.assertIsInstance(decode.by_type(self.FIELD_ARR, 'array')[1], list) def test_decode_by_type_field_array_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'array') def test_decode_by_type_field_array_value(self): value = decode.by_type(self.FIELD_ARR, 'array')[1] for position in range(0, len(value)): if isinstance(value[position], float): self.assertAlmostEqual( round(value[position], 3), round(self.FIELD_ARR_VALUE[position], 3)) else: self.assertEqual(value[position], self.FIELD_ARR_VALUE[position]) def test_decode_by_type_field_table_bytes_consumed(self): self.assertEqual( decode.by_type(self.FIELD_TBL, 'table')[0], len(self.FIELD_TBL)) def test_decode_by_type_field_table_data_type(self): self.assertIsInstance(decode.by_type(self.FIELD_TBL, 'table')[1], dict) def test_decode_by_type_field_table_invalid_value(self): self.assertRaises(ValueError, decode.by_type, None, 'table') def test_decode_by_type_field_table_value(self): value = decode.by_type(self.FIELD_TBL, 'table')[1] for key in self.FIELD_TBL_VALUE.keys(): if isinstance(value[key], float): self.assertAlmostEqual(round(value[key], 3), round(self.FIELD_TBL_VALUE[key], 3)) else: self.assertEqual(value[key], self.FIELD_TBL_VALUE[key]) def test_decode_embedded_value_empty_bytes_consumed(self): self.assertEqual(decode._embedded_value(b'')[0], 0) def test_decode_embedded_value_empty_value(self): self.assertEqual(decode._embedded_value(b'')[1], None) def test_decode_embedded_value_decimal_bytes_consumed(self): value = b'D\x05\x00\x04\xcb/' self.assertEqual(decode._embedded_value(value)[0], len(value)) def test_decode_embedded_value_decimal_data_type(self): value = b'D\x05\x00\x04\xcb/' self.assertIsInstance( decode._embedded_value(value)[1], decimal.Decimal) def test_decode_embedded_value_decimal_value(self): value = b'D\x05\x00\x04\xcb/' self.assertEqual(round(float(decode._embedded_value(value)[1]), 5), round(float(decimal.Decimal('3.14159')), 5)) def test_decode_embedded_value_double_bytes_consumed(self): value = b'dC\x0f\xd8\x91\x14\xb9\xc3\x98' self.assertEqual(decode._embedded_value(value)[0], len(value)) def test_decode_embedded_value_double_data_type(self): value = b'dC\x0f\xd8\x91\x14\xb9\xc3\x98' self.assertIsInstance(decode._embedded_value(value)[1], float) def test_decode_embedded_value_double_value(self): value = b'dC\x0f\xd8\x91\x14\xb9\xc3\x98' self.assertEqual(decode._embedded_value(value)[1], 1120480238450803.0) def test_decode_embedded_value_long_bytes_consumed(self): value = b'I\x7f\xff\xff\xff' self.assertEqual(decode._embedded_value(value)[0], 5) def test_decode_embedded_value_long_data_type(self): value = b'I\x7f\xff\xff\xff' self.assertIsInstance(decode._embedded_value(value)[1], int) def test_decode_embedded_value_long_value(self): value = b'I\x7f\xff\xff\xff' self.assertEqual(decode._embedded_value(value)[1], 2147483647) def test_decode_embedded_value_long_uint_bytes_consumed(self): value = b'i\xff\xff\xff\xff' self.assertEqual(decode._embedded_value(value)[0], 5) def test_decode_embedded_value_long_uint_data_type(self): value = b'i\xff\xff\xff\xff' self.assertIsInstance(decode._embedded_value(value)[1], int) def test_decode_embedded_value_long_uint_value(self): value = b'i\xff\xff\xff\xff' self.assertEqual(decode._embedded_value(value)[1], 4294967295) def test_decode_embedded_value_long_long_bytes_consumed(self): value = b'l\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertEqual(decode._embedded_value(value)[0], 9) @unittest.skipIf(PLATFORM_32BIT, 'Skipped on 32-bit platforms') def test_decode_embedded_value_long_long_data_type_64bit(self): value = b'l\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertIsInstance(decode._embedded_value(value)[1], int) @unittest.skipIf(PLATFORM_64BIT, 'Skipped on 64-bit platforms') def test_decode_embedded_value_long_long_data_type_32bit(self): value = b'l\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertIsInstance(decode._embedded_value(value)[1], long) def test_decode_embedded_value_long_long_value(self): value = b'l\x7f\xff\xff\xff\xff\xff\xff\xf8' self.assertEqual(decode._embedded_value(value)[1], 9223372036854775800) def test_decode_embedded_value_longstr_bytes_consumed(self): value = b'S\x00\x00\x00\n0123456789' self.assertEqual(decode._embedded_value(value)[0], 15) def test_decode_embedded_value_longstr_data_type(self): value = b'S\x00\x00\x00\n0123456789' expectation = bytes if PYTHON3 else str self.assertIsInstance(decode._embedded_value(value)[1], expectation) def test_decode_embedded_value_byte_array_data(self): value = b'x\x00\x00\x00\x03ABC' self.assertEqual( decode._embedded_value(value)[1], bytearray([65, 66, 67])) def test_decode_embedded_value_byte_array_data_type(self): value = b'x\x00\x00\x00\x03ABC' self.assertIsInstance(decode._embedded_value(value)[1], bytearray) def test_decode_embedded_value_longstr_data_type_unicode(self): value = (b'S\x00\x00\x00\x0c\xd8\xa7\xd8\xae\xd8\xaa\xd8\xa8\xd8' b'\xa7\xd8\xb1') self.assertIsInstance(decode._embedded_value(value)[1], bytes) def test_decode_embedded_value_longstr_value(self): value = b'S\x00\x00\x00\n0123456789' self.assertEqual(decode._embedded_value(value)[1], b'0123456789') def test_decode_embedded_value_short_bytes_consumed(self): value = b's\x7f\xff' self.assertEqual(decode._embedded_value(value)[0], 3) def test_decode_embedded_value_short_short_bytes_consumed(self): self.assertEqual(decode._embedded_value(b'b\xff')[0], 2) def test_decode_embedded_value_short_short_data_type(self): self.assertIsInstance(decode._embedded_value(b'b\xff')[1], int) def test_decode_embedded_value_short_short_value(self): self.assertEqual(decode._embedded_value(b'b\xff')[1], 255) def test_decode_embedded_value_short_data_type(self): value = b's\x7f\xff' self.assertIsInstance(decode._embedded_value(value)[1], int) def test_decode_embedded_value_short_value(self): self.assertEqual(decode._embedded_value(b's\x7f\xff')[1], 32767) def test_decode_embedded_value_short_uint_data_type(self): self.assertIsInstance(decode._embedded_value(b'u\xff\xff')[1], int) def test_decode_embedded_value_short_uint_value(self): self.assertEqual(decode._embedded_value(b'u\xff\xff')[1], 65535) def test_decode_embedded_value_timestamp_bytes_consumed(self): value = b'T\x00\x00\x00\x00Ec)\x92' self.assertEqual(decode._embedded_value(value)[0], 9) def test_decode_embedded_value_timestamp_data_type(self): value = b'T\x00\x00\x00\x00Ec)\x92' self.assertIsInstance( decode._embedded_value(value)[1], time.struct_time) def test_decode_embedded_value_timestamp_value(self): value = b'T\x00\x00\x00\x00Ec)\x92' self.assertEqual( decode._embedded_value(value)[1], time.struct_time((2006, 11, 21, 16, 30, 10, 1, 325, 0))) def test_decode_embedded_value_field_array_bytes_consumed(self): self.assertEqual( decode._embedded_value(b'A' + self.FIELD_ARR)[0], len(b'A' + self.FIELD_ARR)) def test_decode_embedded_value_field_array_data_type(self): self.assertIsInstance( decode._embedded_value(b'A' + self.FIELD_ARR)[1], list) def test_decode_embedded_value_field_array_value(self): value = decode._embedded_value(b'A' + self.FIELD_ARR)[1] for position in range(0, len(value)): if isinstance(value[position], float): self.assertAlmostEqual( round(value[position], 3), round(self.FIELD_ARR_VALUE[position], 3)) else: self.assertEqual(value[position], self.FIELD_ARR_VALUE[position]) def test_decode_embedded_value_field_table_bytes_consumed(self): self.assertEqual( decode._embedded_value(b'F' + self.FIELD_TBL)[0], len(b'F' + self.FIELD_TBL)) def test_decode_embedded_value_field_table_data_type(self): self.assertIsInstance( decode._embedded_value(b'F' + self.FIELD_TBL)[1], dict) def test_decode_embedded_value_field_table_value(self): value = decode._embedded_value(b'F' + self.FIELD_TBL)[1] for key in self.FIELD_TBL_VALUE.keys(): if isinstance(value[key], float): self.assertAlmostEqual(round(value[key], 3), round(self.FIELD_TBL_VALUE[key], 3)) else: self.assertEqual(value[key], self.FIELD_TBL_VALUE[key]) def test_decode_embedded_value_void_consumed(self): self.assertEqual(decode._embedded_value(b'V')[0], 1) def test_decode_embedded_value_void_value(self): self.assertIsNone(decode._embedded_value(b'V')[1]) def test_field_embedded_value_field_table_keys(self): value = decode._embedded_value(b'F' + self.FIELD_TBL)[1] self.assertListEqual(sorted(value.keys()), sorted(self.FIELD_TBL_VALUE.keys())) pamqp-2.3.0/tests/test_encode_decode.py000066400000000000000000000010301345615226700201520ustar00rootroot00000000000000# -*- encoding: utf-8 -*- import unittest from pamqp import decode, encode class EncodeDecodeTests(unittest.TestCase): def test_encode_decode_field_table_long_keys(self): """Encoding and decoding a field_table with too long keys.""" # second key is 126 A's + \N{PILE OF POO} data = {'A' * 256: 1, ((b'A' * 128) + b'\xf0\x9f\x92\xa9').decode('utf-8'): 2} encoded = encode.field_table(data) decoded = decode.field_table(encoded)[1] self.assertIn('A' * 128, decoded) pamqp-2.3.0/tests/test_encoding.py000066400000000000000000000445341345615226700172200ustar00rootroot00000000000000# -*- encoding: utf-8 -*- from datetime import datetime from decimal import Decimal import unittest from pamqp import encode, PYTHON3 if PYTHON3: long = int class MarshalingTests(unittest.TestCase): def test_encode_bool_wrong_type(self): self.assertRaises(TypeError, encode.boolean, 'hi') def test_encode_bool_false(self): self.assertEqual(encode.boolean(False), b'\x00') def test_encode_bool_true(self): self.assertEqual(encode.boolean(True), b'\x01') def test_encode_byte_array(self): self.assertEqual(encode.byte_array(bytearray([65, 66, 67])), b'\x00\x00\x00\x03ABC') def test_encode_byte_array_wrong_type(self): self.assertRaises(TypeError, encode.byte_array, b'ABC') def test_encode_decimal_wrong_type(self): self.assertRaises(TypeError, encode.decimal, 3.141597) def test_encode_decimal(self): self.assertEqual(encode.decimal(Decimal('3.14159')), b'\x05\x00\x04\xcb/') def test_encode_decimal_whole(self): self.assertEqual(encode.decimal(Decimal('314159')), b'\x00\x00\x04\xcb/') def test_encode_double_invalid_value(self): self.assertRaises(TypeError, encode.double, '1234') def test_encode_double(self): self.assertEqual(encode.double(float(3.14159)), b'@\t!\xf9\xf0\x1b\x86n') def test_encode_floating_point_type(self): self.assertRaises(TypeError, encode.floating_point, '1234') def test_encode_float(self): self.assertEqual(encode.floating_point(float(3.14159)), b'@I\x0f\xd0') def test_encode_long_int_wrong_type(self): self.assertRaises(TypeError, encode.long_int, 3.141597) def test_encode_table_integer_bad_value_error(self): self.assertRaises(TypeError, encode.long_int, 9223372036854775808) def test_encode_long_int(self): self.assertEqual(encode.long_int(long(2147483647)), b'\x7f\xff\xff\xff') def test_encode_long_int_error(self): self.assertRaises(TypeError, encode.long_int, long(21474836449)) def test_encode_long_uint(self): self.assertEqual(encode.long_uint(long(4294967295)), b'\xff\xff\xff\xff') def test_encode_long_uint_error(self): self.assertRaises(TypeError, encode.long_uint, long(4294967296)) def test_encode_long_uint_wrong_type(self): self.assertRaises(TypeError, encode.long_uint, 3.141597) def test_encode_long_long_int_wrong_type(self): self.assertRaises(TypeError, encode.long_long_int, 3.141597) def test_encode_long_long_int_error(self): self.assertRaises(TypeError, encode.long_long_int, long(9223372036854775808)) def test_encode_octet(self): self.assertEqual(encode.octet(1), b'\x01') def test_encode_octet_error(self): self.assertRaises(TypeError, encode.octet, 'hi') def test_encode_short_wrong_type(self): self.assertRaises(TypeError, encode.short_int, 3.141597) def test_encode_short(self): self.assertEqual(encode.short_int(32767), b'\x7f\xff') def test_encode_short_error(self): self.assertRaises(TypeError, encode.short_int, 32768) def test_encode_short_uint(self): self.assertEqual(encode.short_uint(65535), b'\xff\xff') def test_encode_short_uint_error(self): self.assertRaises(TypeError, encode.short_uint, 65536) def test_encode_short_uint_type_error(self): self.assertRaises(TypeError, encode.short_uint, 'hello') def test_encode_table_integer_error(self): self.assertRaises(TypeError, encode.table_integer, 9223372036854775808) def test_encode_short_string(self): self.assertEqual(encode.short_string('Hello'), b'\x05Hello') def test_encode_short_string_error(self): self.assertRaises(TypeError, encode.short_string, 32768) @unittest.skipIf(PYTHON3, 'Python2 UTF-8 test') def test_encode_short_string_utf8_python2(self): self.assertEqual( encode.short_string('\xf0\x9f\x90\xb0'.decode('utf-8')), b'\x04\xf0\x9f\x90\xb0') @unittest.skipIf(not PYTHON3, 'Python3 UTF-8 test') def test_encode_short_string_utf8_python3(self): self.assertEqual(encode.short_string('🐰'), b'\x04\xf0\x9f\x90\xb0') def test_encode_long_string(self): self.assertEqual(encode.long_string(b'0123456789'), b'\x00\x00\x00\n0123456789') def test_encode_long_string_bytes(self): self.assertEqual(encode.long_string('rabbitmq'), b'\x00\x00\x00\x08rabbitmq') @unittest.skipIf(PYTHON3, 'Python2 UTF-8 test') def test_encode_long_string_utf8_python2(self): self.assertEqual( encode.long_string('\xf0\x9f\x90\xb0'.decode('utf-8')), b'\x00\x00\x00\x04\xf0\x9f\x90\xb0') @unittest.skipIf(not PYTHON3, 'Python3 UTF-8 test') def test_encode_long_string_utf8_python3(self): self.assertEqual(encode.long_string('🐰'), b'\x00\x00\x00\x04\xf0\x9f\x90\xb0') def test_encode_long_string_error(self): self.assertRaises(TypeError, encode.long_string, 100) def test_encode_timestamp_from_datetime(self): self.assertEqual(encode.timestamp(datetime(2006, 11, 21, 16, 30, 10)), b'\x00\x00\x00\x00Ec)\x92') def test_encode_timestamp_from_struct_time(self): value = \ encode.timestamp(datetime(2006, 11, 21, 16, 30, 10).timetuple()) self.assertEqual(value, b'\x00\x00\x00\x00Ec)\x92') def test_encode_timestamp_from_numeric(self): value = encode.timestamp(1555574815) self.assertEqual(value, b'\x00\x00\x00\x00\\\xb80\x1f') def test_encode_timestamp_error(self): self.assertRaises(TypeError, encode.timestamp, 'hi') def test_encode_field_array(self): expectation = (b'\x00\x00\x00:b\x01u\xaf\xc8I\x02bZ\x00S\x00\x00\x00' b'\x04TestT\x00\x00\x00\x00Ec)\x92I\xbb\x9a\xca\x00D' b'\x02\x00\x00\x01:f@H\xf5\xc3i\xc4e5\xffl\x80\x00\x00' b'\x00\x00\x00\x00\x08') data = [ 1, 45000, 40000000, b'Test', datetime(2006, 11, 21, 16, 30, 10), -1147483648, Decimal('3.14'), 3.14, long(3294967295), -9223372036854775800 ] self.assertEqual(encode.field_array(data), expectation) def test_encode_field_array_error(self): self.assertRaises(TypeError, encode.field_array, 'hi') def test_encode_field_table_empty(self): self.assertEqual(encode.field_table(None), b'\x00\x00\x00\x00') def test_encode_field_table_type_error(self): self.assertRaises(TypeError, encode.field_table, [1, 2, 3]) def test_encode_field_table_object(self): self.assertRaises(TypeError, encode.field_table, {'key': encode.field_table}) def test_encode_field_table(self): expectation = (b"\x00\x00\x04'\x08arrayvalA\x00\x00\x00\x06b\x01b" b'\x02b\x03\x07boolvalt\x01\tbytearrayx\x00\x00\x00' b'\x03AAA\x06decvalD\x02\x00\x00\x01:\x07dictvalF\x00' b'\x00\x00\x0c\x03fooS\x00\x00\x00\x03bar\x08floatval' b'f@H\xf5\xc3\x06intvalb\x01\x07longstrS\x00\x00\x03t' b'000000000000000000000000000000000000000000000000000' b'011111111111111111111111111111111111111111111111111' b'112222222222222222222222222222222222222222222222222' b'222111111111111111111111111111111111111111111111111' b'111122222222222222222222222222222222222222222222222' b'222221111111111111111111111111111111111111111111111' b'111111222222222222222222222222222222222222222222222' b'222222211111111111111111111111111111111111111111111' b'111111112222222222222222222222222222222222222222222' b'222222222111111111111111111111111111111111111111111' b'111111111122222222222222222222222222222222222222222' b'222222222221111111111111111111111111111111111111111' b'111111111111222222222222222222222222222222222222222' b'222222222222211111111111111111111111111111111111111' b'111111111111112222222222222222222222222222222222222' b'222222222222222111111111111111111111111111111111111' b'111111111111111100000000000000000000000000000000000' b'00000000000000000\x07longvalI6e&U\x04noneV\x06strva' b'lS\x00\x00\x00\x04Test\x0ctimestampvalT\x00\x00\x00' b'\x00Ec)\x92') data = { 'intval': 1, 'strval': b'Test', 'boolval': True, 'timestampval': datetime(2006, 11, 21, 16, 30, 10), 'decval': Decimal('3.14'), 'floatval': 3.14, 'longval': long(912598613), 'dictval': { b'foo': b'bar' }, 'arrayval': [1, 2, 3], 'none': None, 'bytearray': bytearray((65, 65, 65)), 'longstr': ('0000000000000000000000000000000000000000000000000' '0001111111111111111111111111111111111111111111111' '1111112222222222222222222222222222222222222222222' '2222222221111111111111111111111111111111111111111' '1111111111112222222222222222222222222222222222222' '2222222222222221111111111111111111111111111111111' '1111111111111111112222222222222222222222222222222' '2222222222222222222221111111111111111111111111111' '1111111111111111111111112222222222222222222222222' '2222222222222222222222222221111111111111111111111' '1111111111111111111111111111112222222222222222222' '2222222222222222222222222222222221111111111111111' '1111111111111111111111111111111111112222222222222' '2222222222222222222222222222222222222221111111111' '1111111111111111111111111111111111111111112222222' '2222222222222222222222222222222222222222222221111' '1111111111111111111111111111111111111111111111110' '0000000000000000000000000000000000000000000000000' '00') } self.assertEqual(encode.field_table(data), expectation) def test_encode_by_type_field_array(self): expectation = (b'\x00\x00\x008b\x01sBhu\xaf\xc8S\x00\x00\x00\x04TestT' b'\x00\x00\x00\x00Ec)\x92I\xbb\x9a\xca\x00D\x02\x00' b'\x00\x01:f@H\xf5\xc3i\xc4e5\xffl\x80\x00\x00\x00\x00' b'\x00\x00\x08') data = [ 1, 17000, 45000, b'Test', datetime(2006, 11, 21, 16, 30, 10), -1147483648, Decimal('3.14'), 3.14, long(3294967295), -9223372036854775800 ] self.assertEqual(encode.by_type(data, 'field_array'), expectation) def test_encode_by_type_byte_array(self): self.assertEqual(encode.by_type(bytearray((65, 66, 67)), 'bytearray'), b'\x00\x00\x00\x03ABC') def test_encode_by_type_double(self): self.assertEqual(encode.by_type(float(4294967295), 'double'), b'A\xef\xff\xff\xff\xe0\x00\x00') def test_encode_by_type_long_uint(self): self.assertEqual(encode.by_type(long(4294967295), 'long'), b'\xff\xff\xff\xff') def test_encode_by_type_long_long_int(self): self.assertEqual(encode.by_type(long(9223372036854775800), 'longlong'), b'\x7f\xff\xff\xff\xff\xff\xff\xf8') def test_encode_by_type_long_str(self): self.assertEqual(encode.by_type(b'0123456789', 'longstr'), b'\x00\x00\x00\n0123456789') def test_encode_by_type_none(self): self.assertEqual(encode.by_type(None, 'void'), None) def test_encode_by_type_octet(self): self.assertEqual(encode.by_type(1, 'octet'), b'\x01') def test_encode_by_type_short(self): self.assertEqual(encode.by_type(32767, 'short'), b'\x7f\xff') def test_encode_by_type_timestamp(self): self.assertEqual( encode.by_type(datetime(2006, 11, 21, 16, 30, 10), 'timestamp'), b'\x00\x00\x00\x00Ec)\x92') def test_encode_by_type_field_table(self): expectation = (b'\x00\x00\x04B\x08arrayvalA\x00\x00\x00\x08b\x01s\x10' b'`u\xa4\x10\x07boolvalt\x01\x06decvalD\x02\x00\x00\x01' b':\x07dictvalF\x00\x00\x00\x0c\x03fooS\x00\x00\x00\x03' b'bar\x08floatvalf@H\xf5\xc3\x07longstrS\x00\x00\x03t00' b'00000000000000000000000000000000000000000000000000111' b'11111111111111111111111111111111111111111111111112222' b'22222222222222222222222222222222222222222222222211111' b'11111111111111111111111111111111111111111111111222222' b'22222222222222222222222222222222222222222222221111111' b'11111111111111111111111111111111111111111111122222222' b'22222222222222222222222222222222222222222222111111111' b'11111111111111111111111111111111111111111112222222222' b'22222222222222222222222222222222222222222211111111111' b'11111111111111111111111111111111111111111222222222222' b'22222222222222222222222222222222222222221111111111111' b'11111111111111111111111111111111111111122222222222222' b'22222222222222222222222222222222222222111111111111111' b'11111111111111111111111111111111111112222222222222222' b'22222222222222222222222222222222222211111111111111111' b'11111111111111111111111111111111111000000000000000000' b'0000000000000000000000000000000000\x07longvalI6e&U' b'\x06s32intI\xc4e6\x00\x06s64intl7\x82\xda\xce\x9d\x90' b'\x00\x00\x06strvalS\x00\x00\x00\x04Test\x0ctimestamp' b'valT\x00\x00\x00\x00Ec)\x92\x06u16ints \x00\x06u32int' b'i\xeek(\x00\x05u8bitb ') data = { 'u8bit': 32, 'u16int': 8192, 's32int': -1000000000, 'u32int': 4000000000, 's64int': 4000000000000000000, 'strval': b'Test', 'boolval': True, 'timestampval': datetime(2006, 11, 21, 16, 30, 10), 'decval': Decimal('3.14'), 'floatval': 3.14, 'longval': long(912598613), 'dictval': { b'foo': b'bar' }, 'arrayval': [1, 4192, 42000], 'longstr': ('0000000000000000000000000000000000000000000000000' '0001111111111111111111111111111111111111111111111' '1111112222222222222222222222222222222222222222222' '2222222221111111111111111111111111111111111111111' '1111111111112222222222222222222222222222222222222' '2222222222222221111111111111111111111111111111111' '1111111111111111112222222222222222222222222222222' '2222222222222222222221111111111111111111111111111' '1111111111111111111111112222222222222222222222222' '2222222222222222222222222221111111111111111111111' '1111111111111111111111111111112222222222222222222' '2222222222222222222222222222222221111111111111111' '1111111111111111111111111111111111112222222222222' '2222222222222222222222222222222222222221111111111' '1111111111111111111111111111111111111111112222222' '2222222222222222222222222222222222222222222221111' '1111111111111111111111111111111111111111111111110' '0000000000000000000000000000000000000000000000000' '00') } self.assertEqual(encode.by_type(data, 'table'), expectation) def test_encode_by_type_error(self): self.assertRaises(TypeError, encode.by_type, 12345.12434, 'foo') class EncodeTableIntegerTestCase(unittest.TestCase): def setUp(self): encode.DEPRECATED_RABBITMQ_SUPPORT = False def tearDown(self): encode.DEPRECATED_RABBITMQ_SUPPORT = False def test_table_integer(self): tests = { 'short-short': (32, b'b '), 'short': (1024, b's\x04\x00'), 'short-negative': (-1024, b's\xfc\x00'), 'short-unsigned': (32768, b'u\x80\x00'), 'long': (65536, b'I\x00\x01\x00\x00'), 'long-negative': (65536, b'I\x00\x01\x00\x00'), 'long-unsigned': (4294967295, b'i\xff\xff\xff\xff'), 'long-long': (9223372036854775805, b'l\x7f\xff\xff\xff\xff\xff\xff\xfd'), } for key, value in tests.items(): result = encode.table_integer(value[0]) self.assertEqual(result, value[1], 'encode {} mismatch ({!r} != {!r})'.format( key, result, value[1])) def test_deprecated_table_integer(self): tests = { 'short-short': (32, b'b '), 'short': (1024, b's\x04\x00'), 'short-negative': (-1024, b's\xfc\x00'), 'long': (65536, b'I\x00\x01\x00\x00'), 'long-negative': (65536, b'I\x00\x01\x00\x00'), 'long-long': (2147483648, b'l\x00\x00\x00\x00\x80\x00\x00\x00'), } encode.support_deprecated_rabbitmq() for key, value in tests.items(): result = encode.table_integer(value[0]) self.assertEqual(result, value[1], 'encode {} mismatch ({!r} != {!r})'.format( key, result, value[1])) pamqp-2.3.0/tests/test_frame_marshaling.py000066400000000000000000000056341345615226700207270ustar00rootroot00000000000000# -*- encoding: utf-8 -*- import unittest import uuid from pamqp import body, frame, header, heartbeat, specification class MarshalingTests(unittest.TestCase): def test_protocol_header(self): expectation = b'AMQP\x00\x00\t\x01' response = frame.marshal(header.ProtocolHeader(), 0) self.assertEqual(response, expectation, 'ProtocolHeader did not match expectation') def test_basic_ack(self): expectation = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00P\x00\x00\x00' b'\x00\x00\x00\x00\x01\x00\xce') frame_obj = specification.Basic.Ack(1, False) response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Ack did not match expectation') def test_basic_cancel(self): expectation = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00\x1e\x07' b'ctag1.0\x00\xce') frame_obj = specification.Basic.Cancel(consumer_tag='ctag1.0') response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Cancel did not match expectation') def test_basic_cancelok(self): expectation = (b'\x01\x00\x01\x00\x00\x00\x0c\x00<\x00\x1f\x07' b'ctag1.0\xce') frame_obj = specification.Basic.CancelOk(consumer_tag='ctag1.0') response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Cancel did not match expectation') def test_basic_consume(self): expectation = (b'\x01\x00\x01\x00\x00\x00\x15\x00<\x00\x14\x00' b'\x00\x03bar\x05ctag0\x00\x00\x00\x00\x00\xce') frame_obj = specification.Basic.Consume(0, 'bar', 'ctag0', False, False, False, False) response = frame.marshal(frame_obj, 1) self.assertEqual(response, expectation, 'Basic.Consume did not match expectation') def test_heartbeat(self): expectation = b'\x08\x00\x00\x00\x00\x00\x00\xce' response = frame.marshal(heartbeat.Heartbeat(), 0) self.assertEqual(response, expectation, 'Heartbeat did not match expectation') def test_content_body(self): value = str(uuid.uuid4()).encode('utf-8') expectation = b'\x03\x00\x01\x00\x00\x00$' + value + b'\xce' self.assertEqual(frame.marshal(body.ContentBody(value), 1), expectation) def test_content_header(self): expectation = (b'\x02\x00\x01\x00\x00\x00\x0e\x00<\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\n\x00\x00\xce') self.assertEqual(frame.marshal(header.ContentHeader(body_size=10), 1), expectation) def test_unknown_frame_type(self): with self.assertRaises(ValueError): frame.marshal(self, 1) pamqp-2.3.0/tests/test_frame_unmarshaling.py000066400000000000000000001771601345615226700212760ustar00rootroot00000000000000# -*- encoding: utf-8 -*- import time import unittest from pamqp import body, frame, header, PYTHON3, specification if PYTHON3: long = int basestring = str unicode = None class DemarshalingTests(unittest.TestCase): def test_protocol_header(self): # Decode the frame and validate lengths frame_data = b'AMQP\x00\x00\t\x01' consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 8, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 8)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'ProtocolHeader', ('Frame was of wrong type, expected ProtocolHeader, ' 'received %s' % frame_obj.name)) self.assertEqual((frame_obj.major_version, frame_obj.minor_version, frame_obj.revision), (0, 9, 1), 'Protocol version is incorrect') def test_heartbeat(self): frame_data = b'\x08\x00\x00\x00\x00\x00\x00\xce' consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 8, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 8)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Heartbeat', ('Frame was of wrong type, expected Heartbeat, ' 'received %s' % frame_obj.name)) def test_basic_ack(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00P\x00\x00\x00\x00' b'\x00\x00\x00\x01\x00\xce') expectation = {'multiple': False, 'delivery_tag': 1} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 21, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 21)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Ack', ('Frame was of wrong type, expected Basic.Ack, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_cancel(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00\x1e\x07ctag1.0\x00' b'\xce') expectation = {'consumer_tag': 'ctag1.0', 'nowait': False} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 21, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 21)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Cancel', ('Frame was of wrong type, expected Basic.Cancel, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_cancelok(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x0c\x00<\x00\x1f\x07ctag1.0' b'\xce') expectation = {'consumer_tag': 'ctag1.0'} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 20, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 20)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.CancelOk', ('Frame was of wrong type, expected Basic.CancelOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_consume(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x18\x00<\x00\x14\x00\x00\x04' b'test\x07ctag1.0\x00\x00\x00\x00\x00\xce') expectation = { 'exclusive': False, 'nowait': False, 'no_local': False, 'consumer_tag': 'ctag1.0', 'queue': 'test', 'arguments': {}, 'ticket': 0, 'no_ack': False } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 32, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 32)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Consume', ('Frame was of wrong type, expected Basic.Consume, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_consumeok(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x0c\x00<\x00\x15\x07ctag1.0' b'\xce') expectation = {'consumer_tag': 'ctag1.0'} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 20, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 20)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.ConsumeOk', ('Frame was of wrong type, expected Basic.ConsumeOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_deliver(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x1b\x00<\x00<\x07ctag1.0' b'\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x04test\xce') expectation = { 'consumer_tag': 'ctag1.0', 'delivery_tag': 1, 'redelivered': False, 'exchange': '', 'routing_key': 'test' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 35, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 35)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Deliver', ('Frame was of wrong type, expected Basic.Deliver, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_get(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x0c\x00<\x00F\x00\x00\x04' b'test\x00\xce') expectation = {'queue': 'test', 'ticket': 0, 'no_ack': False} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 20, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 20)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Get', ('Frame was of wrong type, expected Basic.Get, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_getempty(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x05\x00<\x00H\x00\xce' expectation = {'cluster_id': ''} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 13, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 13)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.GetEmpty', ('Frame was of wrong type, expected Basic.GetEmpty, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_getok(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x17\x00<\x00G\x00\x00\x00\x00' b'\x00\x00\x00\x10\x00\x00\x04test\x00\x00\x12\x06\xce') expectation = { 'message_count': 4614, 'redelivered': False, 'routing_key': 'test', 'delivery_tag': 16, 'exchange': '' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 31, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 31)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.GetOk', ('Frame was of wrong type, expected Basic.GetOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_nack(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00x\x00\x00\x00\x00' b'\x00\x00\x00\x01\x00\xce') expectation = {'requeue': False, 'multiple': False, 'delivery_tag': 1} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 21, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 21)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Nack', ('Frame was of wrong type, expected Basic.Nack, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_content_header(self): result = frame.unmarshal(frame.marshal(header.ContentHeader(0, 100), 1)) self.assertEqual(result[2].body_size, 100) def test_content_body(self): result = frame.unmarshal(frame.marshal(body.ContentBody(b'TEST'), 1)) self.assertEqual(len(result[2]), 4) def test_basic_properties(self): encoded_properties = (b'\xff\xfc\x10application/json\x04gzip\x00\x00' b'\x00\x1d\x03bazS\x00\x00\x00\x08Test \xe2\x9c' b'\x88\x03fooS\x00\x00\x00\x03bar\x01\x00$a5304' b'5ef-f174-4621-9ff2-ac0b8fbe6e4a\x12unmarshali' b'ng_tests\n1345274026$746a1902-39dc-47cf-9471-' b'9feecda35660\x00\x00\x00\x00Pj\xb9\x07\x08uni' b'ttest\x04pika\x18frame_unmarshaling_tests\x00') properties = { 'content_type': 'application/json', 'content_encoding': 'gzip', 'headers': { 'foo': b'bar', 'baz': b'Test \xe2\x9c\x88' }, 'delivery_mode': 1, 'priority': 0, 'correlation_id': 'a53045ef-f174-4621-9ff2-ac0b8fbe6e4a', 'reply_to': 'unmarshaling_tests', 'expiration': '1345274026', 'message_id': '746a1902-39dc-47cf-9471-9feecda35660', 'timestamp': time.struct_time((2012, 10, 2, 9, 51, 3, 1, 276, 0)), 'message_type': 'unittest', 'user_id': 'pika', 'app_id': 'frame_unmarshaling_tests', 'cluster_id': '' } obj = header.ContentHeader() offset, flags = obj._get_flags(encoded_properties) # Decode the frame and validate lengths obj = specification.Basic.Properties() obj.unmarshal(flags, encoded_properties[offset:]) for key in properties: self.assertEqual( getattr(obj, key), properties[key], '%r value of %r did not match expectation of %r' % (key, getattr(obj, key), properties[key])) def test_basic_publish(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00(\x00\x00\x00' b'\x04test\x00\xce') expectation = { 'ticket': 0, 'mandatory': False, 'routing_key': 'test', 'immediate': False, 'exchange': '' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 21, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 21)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Publish', ('Frame was of wrong type, expected Basic.Publish, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_qos(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x0b\x00<\x00\n\x00\x00\x00' b'\x00\x00\x01\x00\xce') expectation = { 'prefetch_count': 1, 'prefetch_size': 0, 'global_': False } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 19, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 19)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Qos', ('Frame was of wrong type, expected Basic.Qos, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_qosok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00<\x00\x0b\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.QosOk', ('Frame was of wrong type, expected Basic.QosOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_recover(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x05\x00<\x00n\x00\xce' expectation = {'requeue': False} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 13, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 13)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Recover', ('Frame was of wrong type, expected Basic.Recover, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_recoverasync(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x05\x00<\x00d\x00\xce' expectation = {'requeue': False} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 13, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 13)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual( frame_obj.name, 'Basic.RecoverAsync', ('Frame was of wrong type, expected Basic.RecoverAsync, ' 'received %s' % frame_obj.name)) self.assertDictEqual(dict(frame_obj), expectation) def test_basic_recoverok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00<\x00o\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.RecoverOk', ('Frame was of wrong type, expected Basic.RecoverOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_reject(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00Z\x00\x00\x00\x00' b'\x00\x00\x00\x10\x01\xce') expectation = {'requeue': True, 'delivery_tag': 16} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 21, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 21)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Reject', ('Frame was of wrong type, expected Basic.Reject, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_basic_return(self): frame_data = (b'\x01\x00\x01\x00\x00\x00"\x00<\x002\x00\xc8\x0f' b'Normal shutdown\x03foo\x07foo.bar\xce') expectation = { 'reply_code': 200, 'reply_text': 'Normal shutdown', 'routing_key': 'foo.bar', 'exchange': 'foo' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 42, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 42)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Basic.Return', ('Frame was of wrong type, expected Basic.Return, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_channel_close(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x1a\x00\x14\x00(\x00\xc8\x0f' b'Normal shutdown\x00\x00\x00\x00\xce') expectation = { 'class_id': 0, 'method_id': 0, 'reply_code': 200, 'reply_text': 'Normal shutdown' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 34, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 34)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Channel.Close', ('Frame was of wrong type, expected Channel.Close, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_channel_closeok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00\x14\x00)\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Channel.CloseOk', ('Frame was of wrong type, expected Channel.CloseOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_channel_flow(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x05\x00\x14\x00\x14\x01\xce' expectation = {'active': True} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 13, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 13)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Channel.Flow', ('Frame was of wrong type, expected Channel.Flow, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_channel_flowok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x05\x00\x14\x00\x15\x01\xce' expectation = {'active': True} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 13, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 13)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Channel.FlowOk', ('Frame was of wrong type, expected Channel.FlowOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_channel_open(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x05\x00\x14\x00\n\x00\xce' expectation = {'out_of_band': ''} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 13, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 13)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Channel.Open', ('Frame was of wrong type, expected Channel.Open, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_channel_openok(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x08\x00\x14\x00\x0b\x00\x00' b'\x00\x00\xce') expectation = {'channel_id': b''} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 16, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 16)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Channel.OpenOk', ('Frame was of wrong type, expected Channel.OpenOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_confirm_select(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x05\x00U\x00\n\x00\xce' expectation = {'nowait': False} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 13, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 13)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Confirm.Select', ('Frame was of wrong type, expected Confirm.Select, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_confirm_selectok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00U\x00\x0b\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Confirm.SelectOk', ('Frame was of wrong type, expected ' 'Confirm.SelectOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_close(self): frame_data = (b'\x01\x00\x00\x00\x00\x00\x1a\x00\n\x002\x00\xc8\x0f' b'Normal shutdown\x00\x00\x00\x00\xce') expectation = { 'class_id': 0, 'method_id': 0, 'reply_code': 200, 'reply_text': 'Normal shutdown' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 34, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 34)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.Close', ('Frame was of wrong type, expected ' 'Connection.Close, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_closeok(self): frame_data = b'\x01\x00\x00\x00\x00\x00\x04\x00\n\x003\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.CloseOk', ('Frame was of wrong type, expected ' 'Connection.CloseOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_open(self): frame_data = (b'\x01\x00\x00\x00\x00\x00\x08\x00\n\x00(\x01/\x00' b'\x01\xce') expectation = {'insist': True, 'capabilities': '', 'virtual_host': '/'} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 16, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 16)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.Open', ('Frame was of wrong type, expected Connection.Open, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_openok(self): frame_data = b'\x01\x00\x00\x00\x00\x00\x05\x00\n\x00)\x00\xce' expectation = {'known_hosts': ''} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 13, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 13)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.OpenOk', ('Frame was of wrong type, expected ' 'Connection.OpenOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_secure(self): frame_data = (b'\x01\x00\x00\x00\x00\x00\x08\x00\n\x00\x14\x00\x00' b'\x00\x00\xce') expectation = {'challenge': b''} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 16, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 16)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.Secure', ('Frame was of wrong type, expected ' 'Connection.Secure, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_secureok(self): frame_data = (b'\x01\x00\x00\x00\x00\x00\x08\x00\n\x00\x15\x00\x00' b'\x00\x00\xce') expectation = {'response': b''} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 16, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 16)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.SecureOk', ('Frame was of wrong type, expected ' 'Connection.SecureOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_start(self): frame_data = (b'\x01\x00\x00\x00\x00\x01G\x00\n\x00\n\x00\t' b'\x00\x00\x01"\x0ccapabilitiesF\x00\x00\x00X' b'\x12publisher_confirmst\x01\x1aexchange_exc' b'hange_bindingst\x01\nbasic.nackt\x01\x16con' b'sumer_cancel_notifyt\x01\tcopyrightS\x00' b'\x00\x00$Copyright (C) 2007-2011 VMware, I' b'nc.\x0binformationS\x00\x00\x005Licensed u' b'nder the MPL. See http://www.rabbitmq.com' b'/\x08platformS\x00\x00\x00\nErlang/OTP\x07' b'productS\x00\x00\x00\x08RabbitMQ\x07versio' b'nS\x00\x00\x00\x052.6.1\x00\x00\x00\x0ePLA' b'IN AMQPLAIN\x00\x00\x00\x05en_US\xce') expectation = { 'server_properties': { 'information': (b'Licensed under the MPL. ' b'See http://www.rabbitmq.com/'), 'product': b'RabbitMQ', 'copyright': b'Copyright (C) 2007-2011 VMware, Inc.', 'capabilities': { 'exchange_exchange_bindings': True, 'consumer_cancel_notify': True, 'publisher_confirms': True, 'basic.nack': True }, 'platform': b'Erlang/OTP', 'version': b'2.6.1' }, 'version_minor': 9, 'mechanisms': b'PLAIN AMQPLAIN', 'locales': b'en_US', 'version_major': 0 } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 335, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 335)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.Start', ('Frame was of wrong type, expected ' 'Connection.Start, received %s' % frame_obj.name)) self.maxDiff = 32768 # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_startok(self): frame_data = (b'\x01\x00\x00\x00\x00\x00\xf4\x00\n\x00\x0b' b'\x00\x00\x00\xd0\x08platformS\x00\x00\x00' b'\x0cPython 2.7.1\x07productS\x00\x00\x00' b'\x1aPika Python Client Library\x07versionS' b'\x00\x00\x00\n0.9.6-pre0\x0ccapabilitiesF' b'\x00\x00\x00;\x16consumer_cancel_notifyt' b'\x01\x12publisher_confirmst\x01\nbasic.nack' b't\x01\x0binformationS\x00\x00\x00\x1aSee ' b'http://pika.github.com\x05PLAIN\x00\x00' b'\x00\x0c\x00guest\x00guest\x05en_US\xce') expectation = { 'locale': 'en_US', 'mechanism': 'PLAIN', 'client_properties': { 'platform': b'Python 2.7.1', 'product': b'Pika Python Client Library', 'version': b'0.9.6-pre0', 'capabilities': { 'consumer_cancel_notify': True, 'publisher_confirms': True, 'basic.nack': True }, 'information': b'See http://pika.github.com' }, 'response': b'\x00guest\x00guest' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 252, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 252)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.StartOk', ('Frame was of wrong type, expected ' 'Connection.StartOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_tune(self): frame_data = (b'\x01\x00\x00\x00\x00\x00\x0c\x00\n\x00\x1e\x00\x00' b'\x00\x02\x00\x00\x00\x00\xce') expectation = {'frame_max': 131072, 'channel_max': 0, 'heartbeat': 0} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 20, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 20)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.Tune', ('Frame was of wrong type, expected Connection.Tune, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_connection_tuneok(self): frame_data = (b'\x01\x00\x00\x00\x00\x00\x0c\x00\n\x00\x1f\x00\x00' b'\x00\x02\x00\x00\x00\x00\xce') expectation = {'frame_max': 131072, 'channel_max': 0, 'heartbeat': 0} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 20, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 20)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the frame name self.assertEqual(frame_obj.name, 'Connection.TuneOk', ('Frame was of wrong type, expected ' 'Connection.TuneOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_content_body_frame(self): frame_data = (b'\x03\x00\x00\x00\x00\x00"Hello World #0:1316899165.' b'75516605\xce') expectation = b'Hello World #0:1316899165.75516605' # Decode the frame and validate lengths consumed, channel, data = frame.unmarshal(frame_data) self.assertEqual( consumed, 42, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 42)) self.assertEqual( channel, 0, 'Channel number did not match expectation: %i, %i' % (channel, 0)) # Validate the unmarshaled data matches the expectation self.assertEqual(data.value, expectation) def test_exchange_bind(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x15\x00(\x00\x1e\x00\x00' b'\x00\x00\x07foo.bar\x00\x00\x00\x00\x00\xce') expectation = { 'arguments': {}, 'source': '', 'ticket': 0, 'destination': '', 'nowait': False, 'routing_key': 'foo.bar' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 29, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 29)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Exchange.Bind', ('Frame was of wrong type, expected Exchange.Bind, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_exchange_bindok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00(\x00\x1f\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Exchange.BindOk', ('Frame was of wrong type, expected Exchange.BindOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_exchange_declare(self): frame_data = (b'\x01\x00\x01\x00\x00\x00%\x00(\x00\n\x00\x00\x12pika_' b'test_exchange\x06direct\x00\x00\x00\x00\x00\xce') expectation = { 'nowait': False, 'exchange': 'pika_test_exchange', 'durable': False, 'passive': False, 'internal': False, 'arguments': {}, 'ticket': 0, 'exchange_type': 'direct', 'auto_delete': False } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 45, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 45)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Exchange.Declare', ('Frame was of wrong type, expected ' 'Exchange.Declare, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_exchange_declareok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00(\x00\x0b\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Exchange.DeclareOk', ('Frame was of wrong type, expected Exchange.' 'DeclareOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_exchange_delete(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x1a\x00(\x00\x14\x00\x00\x12' b'pika_test_exchange\x00\xce') expectation = { 'ticket': 0, 'if_unused': False, 'nowait': False, 'exchange': 'pika_test_exchange' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 34, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 34)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Exchange.Delete', ('Frame was of wrong type, expected Exchange.Delete, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_exchange_deleteok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00(\x00\x15\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Exchange.DeleteOk', ('Frame was of wrong type, expected ' 'Exchange.DeleteOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_exchange_unbind(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x15\x00(\x00(\x00\x00\x00' b'\x00\x07foo.bar\x00\x00\x00\x00\x00\xce') expectation = { 'arguments': {}, 'source': '', 'ticket': 0, 'destination': '', 'nowait': False, 'routing_key': 'foo.bar' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 29, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 29)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Exchange.Unbind', ('Frame was of wrong type, expected Exchange.Unbind, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_exchange_unbindok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00(\x003\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Exchange.UnbindOk', ('Frame was of wrong type, expected ' 'Exchange.UnbindOk, received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_bind(self): frame_data = (b'\x01\x00\x01\x00\x00\x00?\x002\x00\x14\x00' b'\x00\x0fpika_test_queue\x12pika_test_excha' b'nge\x10test_routing_key\x00\x00\x00\x00\x00' b'\xce') expectation = { 'nowait': False, 'exchange': 'pika_test_exchange', 'routing_key': 'test_routing_key', 'queue': 'pika_test_queue', 'arguments': {}, 'ticket': 0 } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 71, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 71)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.Bind', ('Frame was of wrong type, expected Queue.Bind, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_bindok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x002\x00\x15\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.BindOk', ('Frame was of wrong type, expected Queue.BindOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_declare(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x10\x002\x00\n\x00\x00\x04' b'test\x02\x00\x00\x00\x00\xce') expectation = { 'passive': False, 'nowait': False, 'exclusive': False, 'durable': True, 'queue': 'test', 'arguments': {}, 'ticket': 0, 'auto_delete': False } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 24, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 24)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.Declare', ('Frame was of wrong type, expected Queue.Declare, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_declareok(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x11\x002\x00\x0b\x04test' b'\x00\x00\x12\x07\x00\x00\x00\x00\xce') expectation = { 'queue': 'test', 'message_count': 4615, 'consumer_count': 0 } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 25, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 25)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.DeclareOk', ('Frame was of wrong type, expected Queue.DeclareOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_delete(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x17\x002\x00(\x00\x00\x0f' b'pika_test_queue\x00\xce') expectation = { 'queue': 'pika_test_queue', 'ticket': 0, 'if_empty': False, 'nowait': False, 'if_unused': False } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 31, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 31)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.Delete', ('Frame was of wrong type, expected Queue.Delete, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_deleteok(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x08\x002\x00)\x00\x00\x00' b'\x00\xce') expectation = {'message_count': 0} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 16, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 16)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.DeleteOk', ('Frame was of wrong type, expected Queue.DeleteOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_purge(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x0c\x002\x00\x1e\x00\x00' b'\x04test\x00\xce') expectation = {'queue': 'test', 'ticket': 0, 'nowait': False} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 20, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 20)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.Purge', ('Frame was of wrong type, expected Queue.Purge, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_purgeok(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x08\x002\x00\x1f\x00\x00\x00' b'\x01\xce') expectation = {'message_count': 1} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 16, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 16)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.PurgeOk', ('Frame was of wrong type, expected Queue.PurgeOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_unbind(self): frame_data = (b'\x01\x00\x01\x00\x00\x00>\x002\x002\x00\x00\x0f' b'pika_test_queue\x12pika_test_exchange\x10test_routing' b'_key\x00\x00\x00\x00\xce') expectation = { 'queue': 'pika_test_queue', 'arguments': {}, 'ticket': 0, 'routing_key': 'test_routing_key', 'exchange': 'pika_test_exchange' } # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 70, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 70)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.Unbind', ('Frame was of wrong type, expected Queue.Unbind, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_queue_unbindok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x002\x003\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Queue.UnbindOk', ('Frame was of wrong type, expected Queue.UnbindOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_tx_commit(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00Z\x00\x14\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Tx.Commit', ('Frame was of wrong type, expected Tx.Commit, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_tx_commitok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00Z\x00\x15\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Tx.CommitOk', ('Frame was of wrong type, expected Tx.CommitOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_tx_rollback(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00Z\x00\x1e\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Tx.Rollback', ('Frame was of wrong type, expected Tx.Rollback, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_tx_rollbackok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00Z\x00\x1f\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Tx.RollbackOk', ('Frame was of wrong type, expected Tx.RollbackOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_tx_select(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00Z\x00\n\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Tx.Select', ('Frame was of wrong type, expected Tx.Select, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) def test_tx_selectok(self): frame_data = b'\x01\x00\x01\x00\x00\x00\x04\x00Z\x00\x0b\xce' expectation = {} # Decode the frame and validate lengths consumed, channel, frame_obj = frame.unmarshal(frame_data) self.assertEqual( consumed, 12, 'Bytes consumed did not match expectation: %i, %i' % (consumed, 12)) self.assertEqual( channel, 1, 'Channel number did not match expectation: %i, %i' % (channel, 1)) # Validate the frame name self.assertEqual(frame_obj.name, 'Tx.SelectOk', ('Frame was of wrong type, expected Tx.SelectOk, ' 'received %s' % frame_obj.name)) # Validate the unmarshaled data matches the expectation self.assertDictEqual(dict(frame_obj), expectation) pamqp-2.3.0/tests/test_frame_unmarshaling_errors.py000066400000000000000000000106331345615226700226610ustar00rootroot00000000000000# coding=utf-8 import struct import unittest from pamqp import exceptions, frame class TestCase(unittest.TestCase): def test_invalid_protocol_header(self): try: frame.unmarshal(b'AMQP\x00\x00\t') except exceptions.UnmarshalingException as err: self.assertTrue(str(err).startswith( "Could not unmarshal " 'frame: Data did not match the ProtocolHeader format')) else: assert False, 'Failed to raise exception' def test_invalid_frame_header(self): frame_data = struct.pack('>BI', 255, 0) try: frame.unmarshal(frame_data) except exceptions.UnmarshalingException as err: self.assertEqual( str(err), 'Could not unmarshal Unknown frame: No frame size') else: assert False, 'Failed to raise exception' def test_frame_with_no_length(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x00\x00<\x00P\x00\x00\x00\x00' b'\x00\x00\x00\x01\x00\xce') try: frame.unmarshal(frame_data) except exceptions.UnmarshalingException as err: self.assertEqual( str(err), 'Could not unmarshal Unknown frame: No frame size') else: assert False, 'Failed to raise exception' def test_frame_malformed_length(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\x0c\x00<\x00P\x00\x00\x00\x00' b'\x00\x00\x00\xce') try: frame.unmarshal(frame_data) except exceptions.UnmarshalingException as err: self.assertEqual( str(err), 'Could not unmarshal Unknown frame: Not all data received') else: assert False, 'Failed to raise exception' def test_frame_malformed_end_byte(self): frame_data = (b'\x01\x00\x01\x00\x00\x00\r\x00<\x00P\x00\x00\x00\x00' b'\x00\x00\x00\x01\x00\x00') try: frame.unmarshal(frame_data) except exceptions.UnmarshalingException as err: self.assertEqual( str(err), 'Could not unmarshal Unknown frame: Last byte error') else: assert False, 'Failed to raise exception' def test_malformed_frame_content(self): payload = struct.pack('>HxxQ', 8192, 32768) frame_value = b''.join([struct.pack('>BHI', 5, 0, len(payload)), payload, frame.FRAME_END_CHAR]) try: frame.unmarshal(frame_value) except exceptions.UnmarshalingException as err: self.assertEqual( str(err), 'Could not unmarshal Unknown frame: Unknown frame type: 5') else: assert False, 'Failed to raise exception' def test_invalid_method_frame_index(self): payload = struct.pack('>L', 42949) frame_value = b''.join([struct.pack('>BHI', 1, 0, len(payload)), payload, frame.FRAME_END_CHAR]) try: frame.unmarshal(frame_value) except exceptions.UnmarshalingException as err: self.assertEqual( str(err), ('Could not unmarshal Unknown frame: ' 'Unknown method index: 42949')) else: assert False, 'Failed to raise exception' def test_invalid_method_frame_content(self): payload = struct.pack('>L', 0x000A0029) frame_value = b''.join([struct.pack('>BHI', 1, 0, len(payload)), payload, frame.FRAME_END_CHAR]) try: frame.unmarshal(frame_value) except exceptions.UnmarshalingException as err: self.assertTrue(str(err).startswith( 'Could not unmarshal L', 0x000A0029) frame_value = b''.join([struct.pack('>BHI', 2, 0, len(payload)), payload, frame.FRAME_END_CHAR]) try: frame.unmarshal(frame_value) except exceptions.UnmarshalingException as err: self.assertTrue(str(err).startswith( 'Could not unmarshal ContentHeader frame:')) else: assert False, 'Failed to raise exception' pamqp-2.3.0/tests/test_specification.py000066400000000000000000002014271345615226700202460ustar00rootroot00000000000000try: import unittest2 as unittest except ImportError: import unittest from pamqp import specification class ArgumentTypeTests(unittest.TestCase): def test_basic_ack_has_delivery_tag(self): self.assertEqual(specification.Basic.Ack.type('delivery_tag'), 'longlong') def test_basic_ack_has_multiple(self): self.assertEqual(specification.Basic.Ack.type('multiple'), 'bit') def test_basic_cancel_has_consumer_tag(self): self.assertEqual(specification.Basic.Cancel.type('consumer_tag'), 'shortstr') def test_basic_cancel_has_nowait(self): self.assertEqual(specification.Basic.Cancel.type('nowait'), 'bit') def test_basic_cancelok_has_consumer_tag(self): self.assertEqual(specification.Basic.CancelOk.type('consumer_tag'), 'shortstr') def test_basic_consume_has_ticket(self): self.assertEqual(specification.Basic.Consume.type('ticket'), 'short') def test_basic_consume_has_queue(self): self.assertEqual(specification.Basic.Consume.type('queue'), 'shortstr') def test_basic_consume_has_consumer_tag(self): self.assertEqual(specification.Basic.Consume.type('consumer_tag'), 'shortstr') def test_basic_consume_has_no_local(self): self.assertEqual(specification.Basic.Consume.type('no_local'), 'bit') def test_basic_consume_has_no_ack(self): self.assertEqual(specification.Basic.Consume.type('no_ack'), 'bit') def test_basic_consume_has_exclusive(self): self.assertEqual(specification.Basic.Consume.type('exclusive'), 'bit') def test_basic_consume_has_nowait(self): self.assertEqual(specification.Basic.Consume.type('nowait'), 'bit') def test_basic_consume_has_arguments(self): self.assertEqual(specification.Basic.Consume.type('arguments'), 'table') def test_basic_consumeok_has_consumer_tag(self): self.assertEqual(specification.Basic.ConsumeOk.type('consumer_tag'), 'shortstr') def test_basic_deliver_has_consumer_tag(self): self.assertEqual(specification.Basic.Deliver.type('consumer_tag'), 'shortstr') def test_basic_deliver_has_delivery_tag(self): self.assertEqual(specification.Basic.Deliver.type('delivery_tag'), 'longlong') def test_basic_deliver_has_redelivered(self): self.assertEqual(specification.Basic.Deliver.type('redelivered'), 'bit') def test_basic_deliver_has_exchange(self): self.assertEqual(specification.Basic.Deliver.type('exchange'), 'shortstr') def test_basic_deliver_has_routing_key(self): self.assertEqual(specification.Basic.Deliver.type('routing_key'), 'shortstr') def test_basic_get_has_ticket(self): self.assertEqual(specification.Basic.Get.type('ticket'), 'short') def test_basic_get_has_queue(self): self.assertEqual(specification.Basic.Get.type('queue'), 'shortstr') def test_basic_get_has_no_ack(self): self.assertEqual(specification.Basic.Get.type('no_ack'), 'bit') def test_basic_getempty_has_cluster_id(self): self.assertEqual(specification.Basic.GetEmpty.type('cluster_id'), 'shortstr') def test_basic_getok_has_delivery_tag(self): self.assertEqual(specification.Basic.GetOk.type('delivery_tag'), 'longlong') def test_basic_getok_has_redelivered(self): self.assertEqual(specification.Basic.GetOk.type('redelivered'), 'bit') def test_basic_getok_has_exchange(self): self.assertEqual(specification.Basic.GetOk.type('exchange'), 'shortstr') def test_basic_getok_has_routing_key(self): self.assertEqual(specification.Basic.GetOk.type('routing_key'), 'shortstr') def test_basic_getok_has_message_count(self): self.assertEqual(specification.Basic.GetOk.type('message_count'), 'long') def test_basic_nack_has_delivery_tag(self): self.assertEqual(specification.Basic.Nack.type('delivery_tag'), 'longlong') def test_basic_nack_has_multiple(self): self.assertEqual(specification.Basic.Nack.type('multiple'), 'bit') def test_basic_nack_has_requeue(self): self.assertEqual(specification.Basic.Nack.type('requeue'), 'bit') def test_basic_publish_has_ticket(self): self.assertEqual(specification.Basic.Publish.type('ticket'), 'short') def test_basic_publish_has_exchange(self): self.assertEqual(specification.Basic.Publish.type('exchange'), 'shortstr') def test_basic_publish_has_routing_key(self): self.assertEqual(specification.Basic.Publish.type('routing_key'), 'shortstr') def test_basic_publish_has_mandatory(self): self.assertEqual(specification.Basic.Publish.type('mandatory'), 'bit') def test_basic_publish_has_immediate(self): self.assertEqual(specification.Basic.Publish.type('immediate'), 'bit') def test_basic_qos_has_prefetch_size(self): self.assertEqual(specification.Basic.Qos.type('prefetch_size'), 'long') def test_basic_qos_has_prefetch_count(self): self.assertEqual(specification.Basic.Qos.type('prefetch_count'), 'short') def test_basic_qos_has_global_(self): self.assertEqual(specification.Basic.Qos.type('global_'), 'bit') def test_basic_recover_has_requeue(self): self.assertEqual(specification.Basic.Recover.type('requeue'), 'bit') def test_basic_recoverasync_has_requeue(self): self.assertEqual(specification.Basic.RecoverAsync.type('requeue'), 'bit') def test_basic_reject_has_delivery_tag(self): self.assertEqual(specification.Basic.Reject.type('delivery_tag'), 'longlong') def test_basic_reject_has_requeue(self): self.assertEqual(specification.Basic.Reject.type('requeue'), 'bit') def test_basic_return_has_reply_code(self): self.assertEqual(specification.Basic.Return.type('reply_code'), 'short') def test_basic_return_has_reply_text(self): self.assertEqual(specification.Basic.Return.type('reply_text'), 'shortstr') def test_basic_return_has_exchange(self): self.assertEqual(specification.Basic.Return.type('exchange'), 'shortstr') def test_basic_return_has_routing_key(self): self.assertEqual(specification.Basic.Return.type('routing_key'), 'shortstr') def test_channel_close_has_reply_code(self): self.assertEqual(specification.Channel.Close.type('reply_code'), 'short') def test_channel_close_has_reply_text(self): self.assertEqual(specification.Channel.Close.type('reply_text'), 'shortstr') def test_channel_close_has_class_id(self): self.assertEqual(specification.Channel.Close.type('class_id'), 'short') def test_channel_close_has_method_id(self): self.assertEqual(specification.Channel.Close.type('method_id'), 'short') def test_channel_flow_has_active(self): self.assertEqual(specification.Channel.Flow.type('active'), 'bit') def test_channel_flowok_has_active(self): self.assertEqual(specification.Channel.FlowOk.type('active'), 'bit') def test_channel_open_has_out_of_band(self): self.assertEqual(specification.Channel.Open.type('out_of_band'), 'shortstr') def test_channel_openok_has_channel_id(self): self.assertEqual(specification.Channel.OpenOk.type('channel_id'), 'longstr') def test_confirm_select_has_nowait(self): self.assertEqual(specification.Confirm.Select.type('nowait'), 'bit') def test_connection_blocked_has_reason(self): self.assertEqual(specification.Connection.Blocked.type('reason'), 'shortstr') def test_connection_close_has_reply_code(self): self.assertEqual(specification.Connection.Close.type('reply_code'), 'short') def test_connection_close_has_reply_text(self): self.assertEqual(specification.Connection.Close.type('reply_text'), 'shortstr') def test_connection_close_has_class_id(self): self.assertEqual(specification.Connection.Close.type('class_id'), 'short') def test_connection_close_has_method_id(self): self.assertEqual(specification.Connection.Close.type('method_id'), 'short') def test_connection_open_has_virtual_host(self): self.assertEqual(specification.Connection.Open.type('virtual_host'), 'shortstr') def test_connection_open_has_capabilities(self): self.assertEqual(specification.Connection.Open.type('capabilities'), 'shortstr') def test_connection_open_has_insist(self): self.assertEqual(specification.Connection.Open.type('insist'), 'bit') def test_connection_openok_has_known_hosts(self): self.assertEqual(specification.Connection.OpenOk.type('known_hosts'), 'shortstr') def test_connection_secure_has_challenge(self): self.assertEqual(specification.Connection.Secure.type('challenge'), 'longstr') def test_connection_secureok_has_response(self): self.assertEqual(specification.Connection.SecureOk.type('response'), 'longstr') def test_connection_start_has_version_major(self): self.assertEqual(specification.Connection.Start.type('version_major'), 'octet') def test_connection_start_has_version_minor(self): self.assertEqual(specification.Connection.Start.type('version_minor'), 'octet') def test_connection_start_has_server_properties(self): self.assertEqual( specification.Connection.Start.type('server_properties'), 'table') def test_connection_start_has_mechanisms(self): self.assertEqual(specification.Connection.Start.type('mechanisms'), 'longstr') def test_connection_start_has_locales(self): self.assertEqual(specification.Connection.Start.type('locales'), 'longstr') def test_connection_startok_has_client_properties(self): self.assertEqual( specification.Connection.StartOk.type('client_properties'), 'table') def test_connection_startok_has_mechanism(self): self.assertEqual(specification.Connection.StartOk.type('mechanism'), 'shortstr') def test_connection_startok_has_response(self): self.assertEqual(specification.Connection.StartOk.type('response'), 'longstr') def test_connection_startok_has_locale(self): self.assertEqual(specification.Connection.StartOk.type('locale'), 'shortstr') def test_connection_tune_has_channel_max(self): self.assertEqual(specification.Connection.Tune.type('channel_max'), 'short') def test_connection_tune_has_frame_max(self): self.assertEqual(specification.Connection.Tune.type('frame_max'), 'long') def test_connection_tune_has_heartbeat(self): self.assertEqual(specification.Connection.Tune.type('heartbeat'), 'short') def test_connection_tuneok_has_channel_max(self): self.assertEqual(specification.Connection.TuneOk.type('channel_max'), 'short') def test_connection_tuneok_has_frame_max(self): self.assertEqual(specification.Connection.TuneOk.type('frame_max'), 'long') def test_connection_tuneok_has_heartbeat(self): self.assertEqual(specification.Connection.TuneOk.type('heartbeat'), 'short') def test_exchange_bind_has_ticket(self): self.assertEqual(specification.Exchange.Bind.type('ticket'), 'short') def test_exchange_bind_has_destination(self): self.assertEqual(specification.Exchange.Bind.type('destination'), 'shortstr') def test_exchange_bind_has_source(self): self.assertEqual(specification.Exchange.Bind.type('source'), 'shortstr') def test_exchange_bind_has_routing_key(self): self.assertEqual(specification.Exchange.Bind.type('routing_key'), 'shortstr') def test_exchange_bind_has_nowait(self): self.assertEqual(specification.Exchange.Bind.type('nowait'), 'bit') def test_exchange_bind_has_arguments(self): self.assertEqual(specification.Exchange.Bind.type('arguments'), 'table') def test_exchange_declare_has_ticket(self): self.assertEqual(specification.Exchange.Declare.type('ticket'), 'short') def test_exchange_declare_has_exchange(self): self.assertEqual(specification.Exchange.Declare.type('exchange'), 'shortstr') def test_exchange_declare_has_exchange_type(self): self.assertEqual(specification.Exchange.Declare.type('exchange_type'), 'shortstr') def test_exchange_declare_has_passive(self): self.assertEqual(specification.Exchange.Declare.type('passive'), 'bit') def test_exchange_declare_has_durable(self): self.assertEqual(specification.Exchange.Declare.type('durable'), 'bit') def test_exchange_declare_has_auto_delete(self): self.assertEqual(specification.Exchange.Declare.type('auto_delete'), 'bit') def test_exchange_declare_has_internal(self): self.assertEqual(specification.Exchange.Declare.type('internal'), 'bit') def test_exchange_declare_has_nowait(self): self.assertEqual(specification.Exchange.Declare.type('nowait'), 'bit') def test_exchange_declare_has_arguments(self): self.assertEqual(specification.Exchange.Declare.type('arguments'), 'table') def test_exchange_delete_has_ticket(self): self.assertEqual(specification.Exchange.Delete.type('ticket'), 'short') def test_exchange_delete_has_exchange(self): self.assertEqual(specification.Exchange.Delete.type('exchange'), 'shortstr') def test_exchange_delete_has_if_unused(self): self.assertEqual(specification.Exchange.Delete.type('if_unused'), 'bit') def test_exchange_delete_has_nowait(self): self.assertEqual(specification.Exchange.Delete.type('nowait'), 'bit') def test_exchange_unbind_has_ticket(self): self.assertEqual(specification.Exchange.Unbind.type('ticket'), 'short') def test_exchange_unbind_has_destination(self): self.assertEqual(specification.Exchange.Unbind.type('destination'), 'shortstr') def test_exchange_unbind_has_source(self): self.assertEqual(specification.Exchange.Unbind.type('source'), 'shortstr') def test_exchange_unbind_has_routing_key(self): self.assertEqual(specification.Exchange.Unbind.type('routing_key'), 'shortstr') def test_exchange_unbind_has_nowait(self): self.assertEqual(specification.Exchange.Unbind.type('nowait'), 'bit') def test_exchange_unbind_has_arguments(self): self.assertEqual(specification.Exchange.Unbind.type('arguments'), 'table') def test_queue_bind_has_ticket(self): self.assertEqual(specification.Queue.Bind.type('ticket'), 'short') def test_queue_bind_has_queue(self): self.assertEqual(specification.Queue.Bind.type('queue'), 'shortstr') def test_queue_bind_has_exchange(self): self.assertEqual(specification.Queue.Bind.type('exchange'), 'shortstr') def test_queue_bind_has_routing_key(self): self.assertEqual(specification.Queue.Bind.type('routing_key'), 'shortstr') def test_queue_bind_has_nowait(self): self.assertEqual(specification.Queue.Bind.type('nowait'), 'bit') def test_queue_bind_has_arguments(self): self.assertEqual(specification.Queue.Bind.type('arguments'), 'table') def test_queue_declare_has_ticket(self): self.assertEqual(specification.Queue.Declare.type('ticket'), 'short') def test_queue_declare_has_queue(self): self.assertEqual(specification.Queue.Declare.type('queue'), 'shortstr') def test_queue_declare_has_passive(self): self.assertEqual(specification.Queue.Declare.type('passive'), 'bit') def test_queue_declare_has_durable(self): self.assertEqual(specification.Queue.Declare.type('durable'), 'bit') def test_queue_declare_has_exclusive(self): self.assertEqual(specification.Queue.Declare.type('exclusive'), 'bit') def test_queue_declare_has_auto_delete(self): self.assertEqual(specification.Queue.Declare.type('auto_delete'), 'bit') def test_queue_declare_has_nowait(self): self.assertEqual(specification.Queue.Declare.type('nowait'), 'bit') def test_queue_declare_has_arguments(self): self.assertEqual(specification.Queue.Declare.type('arguments'), 'table') def test_queue_declareok_has_queue(self): self.assertEqual(specification.Queue.DeclareOk.type('queue'), 'shortstr') def test_queue_declareok_has_message_count(self): self.assertEqual(specification.Queue.DeclareOk.type('message_count'), 'long') def test_queue_declareok_has_consumer_count(self): self.assertEqual(specification.Queue.DeclareOk.type('consumer_count'), 'long') def test_queue_delete_has_ticket(self): self.assertEqual(specification.Queue.Delete.type('ticket'), 'short') def test_queue_delete_has_queue(self): self.assertEqual(specification.Queue.Delete.type('queue'), 'shortstr') def test_queue_delete_has_if_unused(self): self.assertEqual(specification.Queue.Delete.type('if_unused'), 'bit') def test_queue_delete_has_if_empty(self): self.assertEqual(specification.Queue.Delete.type('if_empty'), 'bit') def test_queue_delete_has_nowait(self): self.assertEqual(specification.Queue.Delete.type('nowait'), 'bit') def test_queue_deleteok_has_message_count(self): self.assertEqual(specification.Queue.DeleteOk.type('message_count'), 'long') def test_queue_purge_has_ticket(self): self.assertEqual(specification.Queue.Purge.type('ticket'), 'short') def test_queue_purge_has_queue(self): self.assertEqual(specification.Queue.Purge.type('queue'), 'shortstr') def test_queue_purge_has_nowait(self): self.assertEqual(specification.Queue.Purge.type('nowait'), 'bit') def test_queue_purgeok_has_message_count(self): self.assertEqual(specification.Queue.PurgeOk.type('message_count'), 'long') def test_queue_unbind_has_ticket(self): self.assertEqual(specification.Queue.Unbind.type('ticket'), 'short') def test_queue_unbind_has_queue(self): self.assertEqual(specification.Queue.Unbind.type('queue'), 'shortstr') def test_queue_unbind_has_exchange(self): self.assertEqual(specification.Queue.Unbind.type('exchange'), 'shortstr') def test_queue_unbind_has_routing_key(self): self.assertEqual(specification.Queue.Unbind.type('routing_key'), 'shortstr') def test_queue_unbind_has_arguments(self): self.assertEqual(specification.Queue.Unbind.type('arguments'), 'table') class AttributeInMethodTests(unittest.TestCase): def test_basic_ack_has_delivery_tag(self): self.assertIn('delivery_tag', specification.Basic.Ack()) def test_basic_ack_has_multiple(self): self.assertIn('multiple', specification.Basic.Ack()) def test_basic_cancel_has_consumer_tag(self): self.assertIn('consumer_tag', specification.Basic.Cancel()) def test_basic_cancel_has_nowait(self): self.assertIn('nowait', specification.Basic.Cancel()) def test_basic_cancelok_has_consumer_tag(self): self.assertIn('consumer_tag', specification.Basic.CancelOk()) def test_basic_consume_has_ticket(self): self.assertIn('ticket', specification.Basic.Consume()) def test_basic_consume_has_queue(self): self.assertIn('queue', specification.Basic.Consume()) def test_basic_consume_has_consumer_tag(self): self.assertIn('consumer_tag', specification.Basic.Consume()) def test_basic_consume_has_no_local(self): self.assertIn('no_local', specification.Basic.Consume()) def test_basic_consume_has_no_ack(self): self.assertIn('no_ack', specification.Basic.Consume()) def test_basic_consume_has_exclusive(self): self.assertIn('exclusive', specification.Basic.Consume()) def test_basic_consume_has_nowait(self): self.assertIn('nowait', specification.Basic.Consume()) def test_basic_consume_has_arguments(self): self.assertIn('arguments', specification.Basic.Consume()) def test_basic_consumeok_has_consumer_tag(self): self.assertIn('consumer_tag', specification.Basic.ConsumeOk()) def test_basic_deliver_has_consumer_tag(self): self.assertIn('consumer_tag', specification.Basic.Deliver()) def test_basic_deliver_has_delivery_tag(self): self.assertIn('delivery_tag', specification.Basic.Deliver()) def test_basic_deliver_has_redelivered(self): self.assertIn('redelivered', specification.Basic.Deliver()) def test_basic_deliver_has_exchange(self): self.assertIn('exchange', specification.Basic.Deliver()) def test_basic_deliver_has_routing_key(self): self.assertIn('routing_key', specification.Basic.Deliver()) def test_basic_get_has_ticket(self): self.assertIn('ticket', specification.Basic.Get()) def test_basic_get_has_queue(self): self.assertIn('queue', specification.Basic.Get()) def test_basic_get_has_no_ack(self): self.assertIn('no_ack', specification.Basic.Get()) def test_basic_getempty_has_cluster_id(self): self.assertIn('cluster_id', specification.Basic.GetEmpty()) def test_basic_getok_has_delivery_tag(self): self.assertIn('delivery_tag', specification.Basic.GetOk()) def test_basic_getok_has_redelivered(self): self.assertIn('redelivered', specification.Basic.GetOk()) def test_basic_getok_has_exchange(self): self.assertIn('exchange', specification.Basic.GetOk()) def test_basic_getok_has_routing_key(self): self.assertIn('routing_key', specification.Basic.GetOk()) def test_basic_getok_has_message_count(self): self.assertIn('message_count', specification.Basic.GetOk()) def test_basic_nack_has_delivery_tag(self): self.assertIn('delivery_tag', specification.Basic.Nack()) def test_basic_nack_has_multiple(self): self.assertIn('multiple', specification.Basic.Nack()) def test_basic_nack_has_requeue(self): self.assertIn('requeue', specification.Basic.Nack()) def test_basic_publish_has_ticket(self): self.assertIn('ticket', specification.Basic.Publish()) def test_basic_publish_has_exchange(self): self.assertIn('exchange', specification.Basic.Publish()) def test_basic_publish_has_routing_key(self): self.assertIn('routing_key', specification.Basic.Publish()) def test_basic_publish_has_mandatory(self): self.assertIn('mandatory', specification.Basic.Publish()) def test_basic_publish_has_immediate(self): self.assertIn('immediate', specification.Basic.Publish()) def test_basic_qos_has_prefetch_size(self): self.assertIn('prefetch_size', specification.Basic.Qos()) def test_basic_qos_has_prefetch_count(self): self.assertIn('prefetch_count', specification.Basic.Qos()) def test_basic_qos_has_global_(self): self.assertIn('global_', specification.Basic.Qos()) def test_basic_recover_has_requeue(self): self.assertIn('requeue', specification.Basic.Recover()) def test_basic_reject_has_delivery_tag(self): self.assertIn('delivery_tag', specification.Basic.Reject()) def test_basic_reject_has_requeue(self): self.assertIn('requeue', specification.Basic.Reject()) def test_basic_return_has_reply_code(self): self.assertIn('reply_code', specification.Basic.Return()) def test_basic_return_has_reply_text(self): self.assertIn('reply_text', specification.Basic.Return()) def test_basic_return_has_exchange(self): self.assertIn('exchange', specification.Basic.Return()) def test_basic_return_has_routing_key(self): self.assertIn('routing_key', specification.Basic.Return()) def test_channel_close_has_reply_code(self): self.assertIn('reply_code', specification.Channel.Close()) def test_channel_close_has_reply_text(self): self.assertIn('reply_text', specification.Channel.Close()) def test_channel_close_has_class_id(self): self.assertIn('class_id', specification.Channel.Close()) def test_channel_close_has_method_id(self): self.assertIn('method_id', specification.Channel.Close()) def test_channel_flow_has_active(self): self.assertIn('active', specification.Channel.Flow()) def test_channel_flowok_has_active(self): self.assertIn('active', specification.Channel.FlowOk()) def test_channel_open_has_out_of_band(self): self.assertIn('out_of_band', specification.Channel.Open()) def test_channel_openok_has_channel_id(self): self.assertIn('channel_id', specification.Channel.OpenOk()) def test_confirm_select_has_nowait(self): self.assertIn('nowait', specification.Confirm.Select()) def test_connection_blocked_has_reason(self): self.assertIn('reason', specification.Connection.Blocked()) def test_connection_close_has_reply_code(self): self.assertIn('reply_code', specification.Connection.Close()) def test_connection_close_has_reply_text(self): self.assertIn('reply_text', specification.Connection.Close()) def test_connection_close_has_class_id(self): self.assertIn('class_id', specification.Connection.Close()) def test_connection_close_has_method_id(self): self.assertIn('method_id', specification.Connection.Close()) def test_connection_open_has_virtual_host(self): self.assertIn('virtual_host', specification.Connection.Open()) def test_connection_open_has_capabilities(self): self.assertIn('capabilities', specification.Connection.Open()) def test_connection_open_has_insist(self): self.assertIn('insist', specification.Connection.Open()) def test_connection_openok_has_known_hosts(self): self.assertIn('known_hosts', specification.Connection.OpenOk()) def test_connection_secure_has_challenge(self): self.assertIn('challenge', specification.Connection.Secure()) def test_connection_secureok_has_response(self): self.assertIn('response', specification.Connection.SecureOk()) def test_connection_start_has_version_major(self): self.assertIn('version_major', specification.Connection.Start()) def test_connection_start_has_version_minor(self): self.assertIn('version_minor', specification.Connection.Start()) def test_connection_start_has_server_properties(self): self.assertIn('server_properties', specification.Connection.Start()) def test_connection_start_has_mechanisms(self): self.assertIn('mechanisms', specification.Connection.Start()) def test_connection_start_has_locales(self): self.assertIn('locales', specification.Connection.Start()) def test_connection_startok_has_mechanism(self): self.assertIn('mechanism', specification.Connection.StartOk()) def test_connection_startok_has_response(self): self.assertIn('response', specification.Connection.StartOk()) def test_connection_startok_has_locale(self): self.assertIn('locale', specification.Connection.StartOk()) def test_connection_tune_has_channel_max(self): self.assertIn('channel_max', specification.Connection.Tune()) def test_connection_tune_has_frame_max(self): self.assertIn('frame_max', specification.Connection.Tune()) def test_connection_tune_has_heartbeat(self): self.assertIn('heartbeat', specification.Connection.Tune()) def test_connection_tuneok_has_channel_max(self): self.assertIn('channel_max', specification.Connection.TuneOk()) def test_connection_tuneok_has_frame_max(self): self.assertIn('frame_max', specification.Connection.TuneOk()) def test_connection_tuneok_has_heartbeat(self): self.assertIn('heartbeat', specification.Connection.TuneOk()) def test_exchange_bind_has_ticket(self): self.assertIn('ticket', specification.Exchange.Bind()) def test_exchange_bind_has_destination(self): self.assertIn('destination', specification.Exchange.Bind()) def test_exchange_bind_has_source(self): self.assertIn('source', specification.Exchange.Bind()) def test_exchange_bind_has_routing_key(self): self.assertIn('routing_key', specification.Exchange.Bind()) def test_exchange_bind_has_nowait(self): self.assertIn('nowait', specification.Exchange.Bind()) def test_exchange_bind_has_arguments(self): self.assertIn('arguments', specification.Exchange.Bind()) def test_exchange_declare_has_ticket(self): self.assertIn('ticket', specification.Exchange.Declare()) def test_exchange_declare_has_exchange(self): self.assertIn('exchange', specification.Exchange.Declare()) def test_exchange_declare_has_exchange_type(self): self.assertIn('exchange_type', specification.Exchange.Declare()) def test_exchange_declare_has_passive(self): self.assertIn('passive', specification.Exchange.Declare()) def test_exchange_declare_has_durable(self): self.assertIn('durable', specification.Exchange.Declare()) def test_exchange_declare_has_auto_delete(self): self.assertIn('auto_delete', specification.Exchange.Declare()) def test_exchange_declare_has_internal(self): self.assertIn('internal', specification.Exchange.Declare()) def test_exchange_declare_has_nowait(self): self.assertIn('nowait', specification.Exchange.Declare()) def test_exchange_declare_has_arguments(self): self.assertIn('arguments', specification.Exchange.Declare()) def test_exchange_delete_has_ticket(self): self.assertIn('ticket', specification.Exchange.Delete()) def test_exchange_delete_has_exchange(self): self.assertIn('exchange', specification.Exchange.Delete()) def test_exchange_delete_has_if_unused(self): self.assertIn('if_unused', specification.Exchange.Delete()) def test_exchange_delete_has_nowait(self): self.assertIn('nowait', specification.Exchange.Delete()) def test_exchange_unbind_has_ticket(self): self.assertIn('ticket', specification.Exchange.Unbind()) def test_exchange_unbind_has_destination(self): self.assertIn('destination', specification.Exchange.Unbind()) def test_exchange_unbind_has_source(self): self.assertIn('source', specification.Exchange.Unbind()) def test_exchange_unbind_has_routing_key(self): self.assertIn('routing_key', specification.Exchange.Unbind()) def test_exchange_unbind_has_nowait(self): self.assertIn('nowait', specification.Exchange.Unbind()) def test_exchange_unbind_has_arguments(self): self.assertIn('arguments', specification.Exchange.Unbind()) def test_queue_bind_has_ticket(self): self.assertIn('ticket', specification.Queue.Bind()) def test_queue_bind_has_queue(self): self.assertIn('queue', specification.Queue.Bind()) def test_queue_bind_has_exchange(self): self.assertIn('exchange', specification.Queue.Bind()) def test_queue_bind_has_routing_key(self): self.assertIn('routing_key', specification.Queue.Bind()) def test_queue_bind_has_nowait(self): self.assertIn('nowait', specification.Queue.Bind()) def test_queue_bind_has_arguments(self): self.assertIn('arguments', specification.Queue.Bind()) def test_queue_declare_has_ticket(self): self.assertIn('ticket', specification.Queue.Declare()) def test_queue_declare_has_queue(self): self.assertIn('queue', specification.Queue.Declare()) def test_queue_declare_has_passive(self): self.assertIn('passive', specification.Queue.Declare()) def test_queue_declare_has_durable(self): self.assertIn('durable', specification.Queue.Declare()) def test_queue_declare_has_exclusive(self): self.assertIn('exclusive', specification.Queue.Declare()) def test_queue_declare_has_auto_delete(self): self.assertIn('auto_delete', specification.Queue.Declare()) def test_queue_declare_has_nowait(self): self.assertIn('nowait', specification.Queue.Declare()) def test_queue_declare_has_arguments(self): self.assertIn('arguments', specification.Queue.Declare()) def test_queue_declareok_has_queue(self): self.assertIn('queue', specification.Queue.DeclareOk()) def test_queue_declareok_has_message_count(self): self.assertIn('message_count', specification.Queue.DeclareOk()) def test_queue_declareok_has_consumer_count(self): self.assertIn('consumer_count', specification.Queue.DeclareOk()) def test_queue_delete_has_ticket(self): self.assertIn('ticket', specification.Queue.Delete()) def test_queue_delete_has_queue(self): self.assertIn('queue', specification.Queue.Delete()) def test_queue_delete_has_if_unused(self): self.assertIn('if_unused', specification.Queue.Delete()) def test_queue_delete_has_if_empty(self): self.assertIn('if_empty', specification.Queue.Delete()) def test_queue_delete_has_nowait(self): self.assertIn('nowait', specification.Queue.Delete()) def test_queue_deleteok_has_message_count(self): self.assertIn('message_count', specification.Queue.DeleteOk()) def test_queue_purge_has_ticket(self): self.assertIn('ticket', specification.Queue.Purge()) def test_queue_purge_has_queue(self): self.assertIn('queue', specification.Queue.Purge()) def test_queue_purge_has_nowait(self): self.assertIn('nowait', specification.Queue.Purge()) def test_queue_purgeok_has_message_count(self): self.assertIn('message_count', specification.Queue.PurgeOk()) def test_queue_unbind_has_ticket(self): self.assertIn('ticket', specification.Queue.Unbind()) def test_queue_unbind_has_queue(self): self.assertIn('queue', specification.Queue.Unbind()) def test_queue_unbind_has_exchange(self): self.assertIn('exchange', specification.Queue.Unbind()) def test_queue_unbind_has_routing_key(self): self.assertIn('routing_key', specification.Queue.Unbind()) def test_queue_unbind_has_arguments(self): self.assertIn('arguments', specification.Queue.Unbind()) class DeprecationWarningTests(unittest.TestCase): def test_basic_recoverasync_raises_deprecation_error(self): with self.assertWarns(DeprecationWarning): specification.Basic.RecoverAsync() class BasicPropertiesTests(unittest.TestCase): def test_basic_properties_has_content_type(self): self.assertEqual(specification.Basic.Properties.type('content_type'), 'shortstr') def test_basic_properties_has_content_encoding(self): self.assertEqual( specification.Basic.Properties.type('content_encoding'), 'shortstr') def test_basic_properties_has_headers(self): self.assertEqual(specification.Basic.Properties.type('headers'), 'table') def test_basic_properties_has_delivery_mode(self): self.assertEqual(specification.Basic.Properties.type('delivery_mode'), 'octet') def test_basic_properties_has_priority(self): self.assertEqual(specification.Basic.Properties.type('priority'), 'octet') def test_basic_properties_has_correlation_id(self): self.assertEqual(specification.Basic.Properties.type('correlation_id'), 'shortstr') def test_basic_properties_has_reply_to(self): self.assertEqual(specification.Basic.Properties.type('reply_to'), 'shortstr') def test_basic_properties_has_expiration(self): self.assertEqual(specification.Basic.Properties.type('expiration'), 'shortstr') def test_basic_properties_has_message_id(self): self.assertEqual(specification.Basic.Properties.type('message_id'), 'shortstr') def test_basic_properties_has_timestamp(self): self.assertEqual(specification.Basic.Properties.type('timestamp'), 'timestamp') def test_basic_properties_has_message_type(self): self.assertEqual(specification.Basic.Properties.type('message_type'), 'shortstr') def test_basic_properties_has_user_id(self): self.assertEqual(specification.Basic.Properties.type('user_id'), 'shortstr') def test_basic_properties_has_app_id(self): self.assertEqual(specification.Basic.Properties.type('app_id'), 'shortstr') def test_basic_properties_has_cluster_id(self): self.assertEqual(specification.Basic.Properties.type('cluster_id'), 'shortstr') class MethodAttributeLengthTests(unittest.TestCase): def test_basic_ack_attribute_count(self): self.assertEqual(len(specification.Basic.Ack()), 2) def test_basic_cancel_attribute_count(self): self.assertEqual(len(specification.Basic.Cancel()), 2) def test_basic_cancelok_attribute_count(self): self.assertEqual(len(specification.Basic.CancelOk()), 1) def test_basic_consume_attribute_count(self): self.assertEqual(len(specification.Basic.Consume()), 8) def test_basic_consumeok_attribute_count(self): self.assertEqual(len(specification.Basic.ConsumeOk()), 1) def test_basic_deliver_attribute_count(self): self.assertEqual(len(specification.Basic.Deliver()), 5) def test_basic_get_attribute_count(self): self.assertEqual(len(specification.Basic.Get()), 3) def test_basic_getempty_attribute_count(self): self.assertEqual(len(specification.Basic.GetEmpty()), 1) def test_basic_getok_attribute_count(self): self.assertEqual(len(specification.Basic.GetOk()), 5) def test_basic_nack_attribute_count(self): self.assertEqual(len(specification.Basic.Nack()), 3) def test_basic_publish_attribute_count(self): self.assertEqual(len(specification.Basic.Publish()), 5) def test_basic_qos_attribute_count(self): self.assertEqual(len(specification.Basic.Qos()), 3) def test_basic_qosok_attribute_count(self): self.assertEqual(len(specification.Basic.QosOk()), 0) def test_basic_recover_attribute_count(self): self.assertEqual(len(specification.Basic.Recover()), 1) def test_basic_recoverok_attribute_count(self): self.assertEqual(len(specification.Basic.RecoverOk()), 0) def test_basic_reject_attribute_count(self): self.assertEqual(len(specification.Basic.Reject()), 2) def test_basic_return_attribute_count(self): self.assertEqual(len(specification.Basic.Return()), 4) def test_channel_close_attribute_count(self): self.assertEqual(len(specification.Channel.Close()), 4) def test_channel_closeok_attribute_count(self): self.assertEqual(len(specification.Channel.CloseOk()), 0) def test_channel_flow_attribute_count(self): self.assertEqual(len(specification.Channel.Flow()), 1) def test_channel_flowok_attribute_count(self): self.assertEqual(len(specification.Channel.FlowOk()), 1) def test_channel_open_attribute_count(self): self.assertEqual(len(specification.Channel.Open()), 1) def test_channel_openok_attribute_count(self): self.assertEqual(len(specification.Channel.OpenOk()), 1) def test_confirm_select_attribute_count(self): self.assertEqual(len(specification.Confirm.Select()), 1) def test_confirm_selectok_attribute_count(self): self.assertEqual(len(specification.Confirm.SelectOk()), 0) def test_connection_blocked_attribute_count(self): self.assertEqual(len(specification.Connection.Blocked()), 1) def test_connection_close_attribute_count(self): self.assertEqual(len(specification.Connection.Close()), 4) def test_connection_closeok_attribute_count(self): self.assertEqual(len(specification.Connection.CloseOk()), 0) def test_connection_open_attribute_count(self): self.assertEqual(len(specification.Connection.Open()), 3) def test_connection_openok_attribute_count(self): self.assertEqual(len(specification.Connection.OpenOk()), 1) def test_connection_secure_attribute_count(self): self.assertEqual(len(specification.Connection.Secure()), 1) def test_connection_secureok_attribute_count(self): self.assertEqual(len(specification.Connection.SecureOk()), 1) def test_connection_start_attribute_count(self): self.assertEqual(len(specification.Connection.Start()), 5) def test_connection_startok_attribute_count(self): self.assertEqual(len(specification.Connection.StartOk()), 4) def test_connection_tune_attribute_count(self): self.assertEqual(len(specification.Connection.Tune()), 3) def test_connection_tuneok_attribute_count(self): self.assertEqual(len(specification.Connection.TuneOk()), 3) def test_connection_unblocked_attribute_count(self): self.assertEqual(len(specification.Connection.Unblocked()), 0) def test_exchange_bind_attribute_count(self): self.assertEqual(len(specification.Exchange.Bind()), 6) def test_exchange_bindok_attribute_count(self): self.assertEqual(len(specification.Exchange.BindOk()), 0) def test_exchange_declare_attribute_count(self): self.assertEqual(len(specification.Exchange.Declare()), 9) def test_exchange_declareok_attribute_count(self): self.assertEqual(len(specification.Exchange.DeclareOk()), 0) def test_exchange_delete_attribute_count(self): self.assertEqual(len(specification.Exchange.Delete()), 4) def test_exchange_deleteok_attribute_count(self): self.assertEqual(len(specification.Exchange.DeleteOk()), 0) def test_exchange_unbind_attribute_count(self): self.assertEqual(len(specification.Exchange.Unbind()), 6) def test_exchange_unbindok_attribute_count(self): self.assertEqual(len(specification.Exchange.UnbindOk()), 0) def test_queue_bind_attribute_count(self): self.assertEqual(len(specification.Queue.Bind()), 6) def test_queue_bindok_attribute_count(self): self.assertEqual(len(specification.Queue.BindOk()), 0) def test_queue_declare_attribute_count(self): self.assertEqual(len(specification.Queue.Declare()), 8) def test_queue_declareok_attribute_count(self): self.assertEqual(len(specification.Queue.DeclareOk()), 3) def test_queue_delete_attribute_count(self): self.assertEqual(len(specification.Queue.Delete()), 5) def test_queue_deleteok_attribute_count(self): self.assertEqual(len(specification.Queue.DeleteOk()), 1) def test_queue_purge_attribute_count(self): self.assertEqual(len(specification.Queue.Purge()), 3) def test_queue_purgeok_attribute_count(self): self.assertEqual(len(specification.Queue.PurgeOk()), 1) def test_queue_unbind_attribute_count(self): self.assertEqual(len(specification.Queue.Unbind()), 5) def test_queue_unbindok_attribute_count(self): self.assertEqual(len(specification.Queue.UnbindOk()), 0) def test_tx_commit_attribute_count(self): self.assertEqual(len(specification.Tx.Commit()), 0) def test_tx_commitok_attribute_count(self): self.assertEqual(len(specification.Tx.CommitOk()), 0) def test_tx_rollback_attribute_count(self): self.assertEqual(len(specification.Tx.Rollback()), 0) def test_tx_rollbackok_attribute_count(self): self.assertEqual(len(specification.Tx.RollbackOk()), 0) def test_tx_select_attribute_count(self): self.assertEqual(len(specification.Tx.Select()), 0) def test_tx_selectok_attribute_count(self): self.assertEqual(len(specification.Tx.SelectOk()), 0) class MethodAttributeDefaultTests(unittest.TestCase): def test_basic_ack_default_for_delivery_tag(self): obj = specification.Basic.Ack() self.assertEqual(obj['delivery_tag'], 0) def test_basic_ack_default_for_multiple(self): obj = specification.Basic.Ack() self.assertEqual(obj['multiple'], False) def test_basic_cancel_default_for_consumer_tag(self): obj = specification.Basic.Cancel() self.assertEqual(obj['consumer_tag'], '') def test_basic_cancel_default_for_nowait(self): obj = specification.Basic.Cancel() self.assertEqual(obj['nowait'], False) def test_basic_cancelok_default_for_consumer_tag(self): obj = specification.Basic.CancelOk() self.assertEqual(obj['consumer_tag'], '') def test_basic_consume_default_for_ticket(self): obj = specification.Basic.Consume() self.assertEqual(obj['ticket'], 0) def test_basic_consume_default_for_queue(self): obj = specification.Basic.Consume() self.assertEqual(obj['queue'], '') def test_basic_consume_default_for_consumer_tag(self): obj = specification.Basic.Consume() self.assertEqual(obj['consumer_tag'], '') def test_basic_consume_default_for_no_local(self): obj = specification.Basic.Consume() self.assertEqual(obj['no_local'], False) def test_basic_consume_default_for_no_ack(self): obj = specification.Basic.Consume() self.assertEqual(obj['no_ack'], False) def test_basic_consume_default_for_exclusive(self): obj = specification.Basic.Consume() self.assertEqual(obj['exclusive'], False) def test_basic_consume_default_for_nowait(self): obj = specification.Basic.Consume() self.assertEqual(obj['nowait'], False) def test_basic_consume_default_for_arguments(self): obj = specification.Basic.Consume() self.assertDictEqual(obj['arguments'], {}) def test_basic_consumeok_default_for_consumer_tag(self): obj = specification.Basic.ConsumeOk() self.assertEqual(obj['consumer_tag'], '') def test_basic_deliver_default_for_consumer_tag(self): obj = specification.Basic.Deliver() self.assertEqual(obj['consumer_tag'], '') def test_basic_deliver_default_for_delivery_tag(self): obj = specification.Basic.Deliver() self.assertEqual(obj['delivery_tag'], None) def test_basic_deliver_default_for_redelivered(self): obj = specification.Basic.Deliver() self.assertEqual(obj['redelivered'], False) def test_basic_deliver_default_for_exchange(self): obj = specification.Basic.Deliver() self.assertEqual(obj['exchange'], '') def test_basic_deliver_default_for_routing_key(self): obj = specification.Basic.Deliver() self.assertEqual(obj['routing_key'], '') def test_basic_get_default_for_ticket(self): obj = specification.Basic.Get() self.assertEqual(obj['ticket'], 0) def test_basic_get_default_for_queue(self): obj = specification.Basic.Get() self.assertEqual(obj['queue'], '') def test_basic_get_default_for_no_ack(self): obj = specification.Basic.Get() self.assertEqual(obj['no_ack'], False) def test_basic_getempty_default_for_cluster_id(self): obj = specification.Basic.GetEmpty() self.assertEqual(obj['cluster_id'], '') def test_basic_getok_default_for_delivery_tag(self): obj = specification.Basic.GetOk() self.assertEqual(obj['delivery_tag'], None) def test_basic_getok_default_for_redelivered(self): obj = specification.Basic.GetOk() self.assertEqual(obj['redelivered'], False) def test_basic_getok_default_for_exchange(self): obj = specification.Basic.GetOk() self.assertEqual(obj['exchange'], '') def test_basic_getok_default_for_routing_key(self): obj = specification.Basic.GetOk() self.assertEqual(obj['routing_key'], '') def test_basic_getok_default_for_message_count(self): obj = specification.Basic.GetOk() self.assertEqual(obj['message_count'], 0) def test_basic_nack_default_for_delivery_tag(self): obj = specification.Basic.Nack() self.assertEqual(obj['delivery_tag'], 0) def test_basic_nack_default_for_multiple(self): obj = specification.Basic.Nack() self.assertEqual(obj['multiple'], False) def test_basic_nack_default_for_requeue(self): obj = specification.Basic.Nack() self.assertEqual(obj['requeue'], True) def test_basic_publish_default_for_ticket(self): obj = specification.Basic.Publish() self.assertEqual(obj['ticket'], 0) def test_basic_publish_default_for_exchange(self): obj = specification.Basic.Publish() self.assertEqual(obj['exchange'], '') def test_basic_publish_default_for_routing_key(self): obj = specification.Basic.Publish() self.assertEqual(obj['routing_key'], '') def test_basic_publish_default_for_mandatory(self): obj = specification.Basic.Publish() self.assertEqual(obj['mandatory'], False) def test_basic_publish_default_for_immediate(self): obj = specification.Basic.Publish() self.assertEqual(obj['immediate'], False) def test_basic_qos_default_for_prefetch_size(self): obj = specification.Basic.Qos() self.assertEqual(obj['prefetch_size'], 0) def test_basic_qos_default_for_prefetch_count(self): obj = specification.Basic.Qos() self.assertEqual(obj['prefetch_count'], 0) def test_basic_qos_default_for_global_(self): obj = specification.Basic.Qos() self.assertEqual(obj['global_'], False) def test_basic_recover_default_for_requeue(self): obj = specification.Basic.Recover() self.assertEqual(obj['requeue'], False) def test_basic_reject_default_for_delivery_tag(self): obj = specification.Basic.Reject() self.assertEqual(obj['delivery_tag'], None) def test_basic_reject_default_for_requeue(self): obj = specification.Basic.Reject() self.assertEqual(obj['requeue'], True) def test_basic_return_default_for_reply_code(self): obj = specification.Basic.Return() self.assertEqual(obj['reply_code'], 0) def test_basic_return_default_for_reply_text(self): obj = specification.Basic.Return() self.assertEqual(obj['reply_text'], '') def test_basic_return_default_for_exchange(self): obj = specification.Basic.Return() self.assertEqual(obj['exchange'], '') def test_basic_return_default_for_routing_key(self): obj = specification.Basic.Return() self.assertEqual(obj['routing_key'], '') def test_channel_close_default_for_reply_code(self): obj = specification.Channel.Close() self.assertEqual(obj['reply_code'], 0) def test_channel_close_default_for_reply_text(self): obj = specification.Channel.Close() self.assertEqual(obj['reply_text'], '') def test_channel_close_default_for_class_id(self): obj = specification.Channel.Close() self.assertEqual(obj['class_id'], 0) def test_channel_close_default_for_method_id(self): obj = specification.Channel.Close() self.assertEqual(obj['method_id'], 0) def test_channel_flow_default_for_active(self): obj = specification.Channel.Flow() self.assertEqual(obj['active'], None) def test_channel_flowok_default_for_active(self): obj = specification.Channel.FlowOk() self.assertEqual(obj['active'], None) def test_channel_open_default_for_out_of_band(self): obj = specification.Channel.Open() self.assertEqual(obj['out_of_band'], '') def test_channel_openok_default_for_channel_id(self): obj = specification.Channel.OpenOk() self.assertEqual(obj['channel_id'], '') def test_confirm_select_default_for_nowait(self): obj = specification.Confirm.Select() self.assertEqual(obj['nowait'], False) def test_connection_blocked_default_for_reason(self): obj = specification.Connection.Blocked() self.assertEqual(obj['reason'], '') def test_connection_close_default_for_reply_code(self): obj = specification.Connection.Close() self.assertEqual(obj['reply_code'], 0) def test_connection_close_default_for_reply_text(self): obj = specification.Connection.Close() self.assertEqual(obj['reply_text'], '') def test_connection_close_default_for_class_id(self): obj = specification.Connection.Close() self.assertEqual(obj['class_id'], 0) def test_connection_close_default_for_method_id(self): obj = specification.Connection.Close() self.assertEqual(obj['method_id'], 0) def test_connection_open_default_for_virtual_host(self): obj = specification.Connection.Open() self.assertEqual(obj['virtual_host'], '/') def test_connection_open_default_for_capabilities(self): obj = specification.Connection.Open() self.assertEqual(obj['capabilities'], '') def test_connection_open_default_for_insist(self): obj = specification.Connection.Open() self.assertEqual(obj['insist'], False) def test_connection_openok_default_for_known_hosts(self): obj = specification.Connection.OpenOk() self.assertEqual(obj['known_hosts'], '') def test_connection_secure_default_for_challenge(self): obj = specification.Connection.Secure() self.assertEqual(obj['challenge'], '') def test_connection_secureok_default_for_response(self): obj = specification.Connection.SecureOk() self.assertEqual(obj['response'], '') def test_connection_start_default_for_version_major(self): obj = specification.Connection.Start() self.assertEqual(obj['version_major'], 0) def test_connection_start_default_for_version_minor(self): obj = specification.Connection.Start() self.assertEqual(obj['version_minor'], 9) def test_connection_start_default_for_mechanisms(self): obj = specification.Connection.Start() self.assertEqual(obj['mechanisms'], 'PLAIN') def test_connection_start_default_for_locales(self): obj = specification.Connection.Start() self.assertEqual(obj['locales'], 'en_US') def test_connection_startok_default_for_mechanism(self): obj = specification.Connection.StartOk() self.assertEqual(obj['mechanism'], 'PLAIN') def test_connection_startok_default_for_response(self): obj = specification.Connection.StartOk() self.assertEqual(obj['response'], '') def test_connection_startok_default_for_locale(self): obj = specification.Connection.StartOk() self.assertEqual(obj['locale'], 'en_US') def test_connection_tune_default_for_channel_max(self): obj = specification.Connection.Tune() self.assertEqual(obj['channel_max'], 0) def test_connection_tune_default_for_frame_max(self): obj = specification.Connection.Tune() self.assertEqual(obj['frame_max'], 0) def test_connection_tune_default_for_heartbeat(self): obj = specification.Connection.Tune() self.assertEqual(obj['heartbeat'], 0) def test_connection_tuneok_default_for_channel_max(self): obj = specification.Connection.TuneOk() self.assertEqual(obj['channel_max'], 0) def test_connection_tuneok_default_for_frame_max(self): obj = specification.Connection.TuneOk() self.assertEqual(obj['frame_max'], 0) def test_connection_tuneok_default_for_heartbeat(self): obj = specification.Connection.TuneOk() self.assertEqual(obj['heartbeat'], 0) def test_exchange_bind_default_for_ticket(self): obj = specification.Exchange.Bind() self.assertEqual(obj['ticket'], 0) def test_exchange_bind_default_for_destination(self): obj = specification.Exchange.Bind() self.assertEqual(obj['destination'], '') def test_exchange_bind_default_for_source(self): obj = specification.Exchange.Bind() self.assertEqual(obj['source'], '') def test_exchange_bind_default_for_routing_key(self): obj = specification.Exchange.Bind() self.assertEqual(obj['routing_key'], '') def test_exchange_bind_default_for_nowait(self): obj = specification.Exchange.Bind() self.assertEqual(obj['nowait'], False) def test_exchange_bind_default_for_arguments(self): obj = specification.Exchange.Bind() self.assertDictEqual(obj['arguments'], {}) def test_exchange_declare_default_for_ticket(self): obj = specification.Exchange.Declare() self.assertEqual(obj['ticket'], 0) def test_exchange_declare_default_for_exchange(self): obj = specification.Exchange.Declare() self.assertEqual(obj['exchange'], '') def test_exchange_declare_default_for_exchange_type(self): obj = specification.Exchange.Declare() self.assertEqual(obj['exchange_type'], 'direct') def test_exchange_declare_default_for_passive(self): obj = specification.Exchange.Declare() self.assertEqual(obj['passive'], False) def test_exchange_declare_default_for_durable(self): obj = specification.Exchange.Declare() self.assertEqual(obj['durable'], False) def test_exchange_declare_default_for_auto_delete(self): obj = specification.Exchange.Declare() self.assertEqual(obj['auto_delete'], False) def test_exchange_declare_default_for_internal(self): obj = specification.Exchange.Declare() self.assertEqual(obj['internal'], False) def test_exchange_declare_default_for_nowait(self): obj = specification.Exchange.Declare() self.assertEqual(obj['nowait'], False) def test_exchange_declare_default_for_arguments(self): obj = specification.Exchange.Declare() self.assertDictEqual(obj['arguments'], {}) def test_exchange_delete_default_for_ticket(self): obj = specification.Exchange.Delete() self.assertEqual(obj['ticket'], 0) def test_exchange_delete_default_for_exchange(self): obj = specification.Exchange.Delete() self.assertEqual(obj['exchange'], '') def test_exchange_delete_default_for_if_unused(self): obj = specification.Exchange.Delete() self.assertEqual(obj['if_unused'], False) def test_exchange_delete_default_for_nowait(self): obj = specification.Exchange.Delete() self.assertEqual(obj['nowait'], False) def test_exchange_unbind_default_for_ticket(self): obj = specification.Exchange.Unbind() self.assertEqual(obj['ticket'], 0) def test_exchange_unbind_default_for_destination(self): obj = specification.Exchange.Unbind() self.assertEqual(obj['destination'], '') def test_exchange_unbind_default_for_source(self): obj = specification.Exchange.Unbind() self.assertEqual(obj['source'], '') def test_exchange_unbind_default_for_routing_key(self): obj = specification.Exchange.Unbind() self.assertEqual(obj['routing_key'], '') def test_exchange_unbind_default_for_nowait(self): obj = specification.Exchange.Unbind() self.assertEqual(obj['nowait'], False) def test_exchange_unbind_default_for_arguments(self): obj = specification.Exchange.Unbind() self.assertDictEqual(obj['arguments'], {}) def test_queue_bind_default_for_ticket(self): obj = specification.Queue.Bind() self.assertEqual(obj['ticket'], 0) def test_queue_bind_default_for_queue(self): obj = specification.Queue.Bind() self.assertEqual(obj['queue'], '') def test_queue_bind_default_for_exchange(self): obj = specification.Queue.Bind() self.assertEqual(obj['exchange'], '') def test_queue_bind_default_for_routing_key(self): obj = specification.Queue.Bind() self.assertEqual(obj['routing_key'], '') def test_queue_bind_default_for_nowait(self): obj = specification.Queue.Bind() self.assertEqual(obj['nowait'], False) def test_queue_bind_default_for_arguments(self): obj = specification.Queue.Bind() self.assertDictEqual(obj['arguments'], {}) def test_queue_declare_default_for_ticket(self): obj = specification.Queue.Declare() self.assertEqual(obj['ticket'], 0) def test_queue_declare_default_for_queue(self): obj = specification.Queue.Declare() self.assertEqual(obj['queue'], '') def test_queue_declare_default_for_passive(self): obj = specification.Queue.Declare() self.assertEqual(obj['passive'], False) def test_queue_declare_default_for_durable(self): obj = specification.Queue.Declare() self.assertEqual(obj['durable'], False) def test_queue_declare_default_for_exclusive(self): obj = specification.Queue.Declare() self.assertEqual(obj['exclusive'], False) def test_queue_declare_default_for_auto_delete(self): obj = specification.Queue.Declare() self.assertEqual(obj['auto_delete'], False) def test_queue_declare_default_for_nowait(self): obj = specification.Queue.Declare() self.assertEqual(obj['nowait'], False) def test_queue_declare_default_for_arguments(self): obj = specification.Queue.Declare() self.assertDictEqual(obj['arguments'], {}) def test_queue_declareok_default_for_queue(self): obj = specification.Queue.DeclareOk() self.assertEqual(obj['queue'], '') def test_queue_declareok_default_for_message_count(self): obj = specification.Queue.DeclareOk() self.assertEqual(obj['message_count'], 0) def test_queue_declareok_default_for_consumer_count(self): obj = specification.Queue.DeclareOk() self.assertEqual(obj['consumer_count'], 0) def test_queue_delete_default_for_ticket(self): obj = specification.Queue.Delete() self.assertEqual(obj['ticket'], 0) def test_queue_delete_default_for_queue(self): obj = specification.Queue.Delete() self.assertEqual(obj['queue'], '') def test_queue_delete_default_for_if_unused(self): obj = specification.Queue.Delete() self.assertEqual(obj['if_unused'], False) def test_queue_delete_default_for_if_empty(self): obj = specification.Queue.Delete() self.assertEqual(obj['if_empty'], False) def test_queue_delete_default_for_nowait(self): obj = specification.Queue.Delete() self.assertEqual(obj['nowait'], False) def test_queue_deleteok_default_for_message_count(self): obj = specification.Queue.DeleteOk() self.assertEqual(obj['message_count'], 0) def test_queue_purge_default_for_ticket(self): obj = specification.Queue.Purge() self.assertEqual(obj['ticket'], 0) def test_queue_purge_default_for_queue(self): obj = specification.Queue.Purge() self.assertEqual(obj['queue'], '') def test_queue_purge_default_for_nowait(self): obj = specification.Queue.Purge() self.assertEqual(obj['nowait'], False) def test_queue_purgeok_default_for_message_count(self): obj = specification.Queue.PurgeOk() self.assertEqual(obj['message_count'], 0) def test_queue_unbind_default_for_ticket(self): obj = specification.Queue.Unbind() self.assertEqual(obj['ticket'], 0) def test_queue_unbind_default_for_queue(self): obj = specification.Queue.Unbind() self.assertEqual(obj['queue'], '') def test_queue_unbind_default_for_exchange(self): obj = specification.Queue.Unbind() self.assertEqual(obj['exchange'], '') def test_queue_unbind_default_for_routing_key(self): obj = specification.Queue.Unbind() self.assertEqual(obj['routing_key'], '') def test_queue_unbind_default_for_arguments(self): obj = specification.Queue.Unbind() self.assertDictEqual(obj['arguments'], {}) pamqp-2.3.0/tools/000077500000000000000000000000001345615226700140055ustar00rootroot00000000000000pamqp-2.3.0/tools/codegen.py000077500000000000000000000636371345615226700160050ustar00rootroot00000000000000#!/usr/bin/env python """Generates the pamqp/specification.py file used as a foundation for AMQP communication. """ import copy import datetime import json import keyword from os import path import textwrap import urllib import lxml.etree __author__ = 'Gavin M. Roy' __email__ = 'gavinmroy@gmail.com' __since__ = '2011-03-31' CODEGEN_DIR = '../codegen/' CODEGEN_IGNORE_CLASSES = ['access'] CODEGEN_JSON = CODEGEN_DIR + 'amqp-rabbitmq-0.9.1.json' CODEGEN_XML = CODEGEN_DIR + 'amqp0-9-1.xml' CODEGEN_OUTPUT = '../pamqp/specification.py' CODEGEN_JSON_URL = ('https://raw.githubusercontent.com/rabbitmq/' 'rabbitmq-codegen/master/amqp-rabbitmq-0.9.1.json') CODEGEN_XML_URL = 'http://www.rabbitmq.com/resources/specs/amqp0-9-1.xml' XPATH_ORDER = ['class', 'constant', 'method', 'field'] PREPEND = [CODEGEN_DIR + 'include.py'] # Output buffer list output = [] def new_line(text='', indent_value=0, secondary_indent=0): """Append a new line to the output buffer""" global output if not text: output.append(text) return initial = ''.rjust(indent_value) secondary = ''.rjust(secondary_indent or indent_value) wrapper = textwrap.TextWrapper( width=79, drop_whitespace=True, initial_indent=initial, subsequent_indent=secondary) for value in wrapper.wrap(text.rstrip()): output.append(value) def classify(text): """Replace the AMQP constant with a more pythonic classname""" parts = text.split('-') value = '' for part in parts: value += part.title() return value def comment(text, indent_value=0, prefix='# '): """Append a comment to the output buffer""" for value in get_comments(text, indent_value + len(prefix), prefix): new_line(value) def get_comments(text, indent_value=0, prefix='# '): """Return a list of lines for a given comment with the comment prefix""" indent_text = prefix.rjust(indent_value) values = [] for value in textwrap.wrap(text, 79 - len(indent_text)): values.append(indent_text + value) return values def dashify(text): """Replace a - with a _ for the passed in text""" return text.replace('-', '_') def pep8_class_name(value): """Returns a class name in the proper case per PEP8""" return_value = [] parts = value.split('-') for part in parts: return_value.append(part[0:1].upper() + part[1:]) return ''.join(return_value) def get_class_definition(cls_name, cls_list): """Iterates through class_list trying to match the name against what was passed in. """ for cls_def in cls_list: if cls_def['name'] == cls_name: return cls_def def get_documentation(search_path): """Find the documentation in the xpath :param search_path: :return: """ search = [] for k in XPATH_ORDER: if k in search_path: search.append('%s[@name="%s"]' % (k, search_path[k])) node = xml.xpath('%s/doc' % '/'.join(search)) # Did we not find it? Look for a RabbitMQ extension if not node: node = rabbitmq.xpath('%s/doc' % '/'.join(search)) # Look for RabbitMQ extensions of methods if not node and 'field' in search_path: node = rabbitmq.xpath('field[@name="%s"]/doc' % search_path['method']) # Look for RabbitMQ extensions of fields if not node and 'field' in search_path: node = rabbitmq.xpath('field[@name="%s"]/doc' % search_path['field']) # if we found it, strip all the whitespace if node: return ' '.join([l.strip() for l in node[0].text.split('\n')]).strip() def get_label(search_path): """Look to see if documented & if so, provide the doc as a comment :param search_path: :return: """ search = [] for k in XPATH_ORDER: if k in search_path: search.append('%s[@name="%s"]' % (k, search_path[k])) node = xml.xpath('%s' % '/'.join(search)) if not node: node = rabbitmq.xpath('%s' % '/'.join(search)) # Did it have a value by default? if node and 'label' in node[0].attrib: return (node[0].attrib['label'][0:1].upper() + node[0].attrib['label'][1:]) elif node and node[0].text: return (node[0].text.strip()[0:1].upper() + node[0].text.strip()[1:].strip()) # Look in domains if 'field' in search_path: node = xml.xpath('//amqp/domain[@name="%s"]' % search_path['field']) if node and 'label' in node[0].attrib: return (node[0].attrib['label'][0:1].upper() + node[0].attrib['label'][1:]) # Look for RabbitMQ extensions of fields if 'field' in search_path: node = rabbitmq.xpath('field[@name="%s"]' % search_path['field']) if node and 'label' in node[0].attrib: return (node[0].attrib['label'][0:1].upper() + node[0].attrib['label'][1:]) elif node and node[0].text: return (node[0].text.strip()[0:1].upper() + node[0].text.strip()[1:].strip()) print('Label could not find %r' % search_path) def argument_name(n): """Returns a valid python argument name for the AMQP argument passed in :param str n: The argument name """ value = n.replace('-', '_') if value in keyword.kwlist: value += '_' return value def get_argument_type_doc(arg): """Get the type of the argument for the doc :param arg: :return: str """ if 'domain' in arg: for d, dt in amqp['domains']: if arg['domain'] == d: arg['type'] = dt break if 'type' in arg: if arg['type'] == 'bit': return 'bool' elif arg['type'] == 'long': return 'int/long' elif arg['type'] == 'longlong': return 'int/long' elif arg['type'] == 'longstr': return 'str' elif arg['type'] == 'octet': return 'int' elif arg['type'] == 'short': return 'int' elif arg['type'] == 'shortstr': return 'str' elif arg['type'] == 'table': return 'dict' elif arg['type'] == 'timestamp': return 'struct_time' return 'Unknown' def get_argument_type(arg): """Get the argument type. :param arg: :return: str """ if 'domain' in arg: for d, dt in amqp['domains']: if arg['domain'] == d: arg['type'] = dt break if 'type' in arg: return arg['type'] return 'Unknown' def new_function(function_name, args_in, indent_value=0): """Create a new function :param function_name: :param args_in: :param indent_value: :return: """ global output args = ['self'] for a in args_in: n = argument_name(a['name']) if 'default-value' in a and a['default-value'] != '': if a['default-value'] in keyword.kwlist or \ isinstance(a['default-value'], (bool, int)): value = a['default-value'] else: if isinstance(a['default-value'], basestring): value = "'%s'" % str(a['default-value']) else: value = '%r' % a['default-value'] else: if a['type'][-3:] == 'str': value = "''" elif a['type'] in ['short', 'long']: value = 0 else: value = 'None' if value == '{}': if a['type'][-3:] == 'str': value = "''" elif a['type'] in ['short', 'long']: value = 0 else: value = 'None' args.append('%s=%s' % (n, value)) # Get the definition line built def_line = 'def %s(%s):' % (function_name, ', '.join(args)) # Build the output of it with wrapping indent_str = ''.join( [' ' for _x in range(indent_value + len(function_name) + 5)]) lines = textwrap.wrap( ''.join([' ' for _x in range(indent_value)]) + def_line, 79, subsequent_indent=indent_str) for l in lines: new_line(l) # Check to see if we have the codegen json file in this directory if not path.exists(CODEGEN_JSON): # Retrieve the codegen archive print('Downloading codegen JSON file to %s.' % CODEGEN_JSON) json_data = urllib.urlopen(CODEGEN_JSON_URL) # Write out the JSON file with open(CODEGEN_JSON, 'w') as handle: handle.write(json_data.read()) json_data.close() # Read in the codegen JSON file with open(CODEGEN_JSON, 'r') as handle: amqp = json.load(handle) # Check to see if we have the codegen xml file in this directory if not path.exists(CODEGEN_XML): # Retrieve the codegen XML definition print('Downloading codegen XML file.') handle = urllib.urlopen(CODEGEN_XML_URL) xml_content = handle.read() # Write out the XML file with open(CODEGEN_XML, 'w') as handle: handle.write(xml_content) # Read in the codegen XML file with open(CODEGEN_XML, 'r') as handle: amqp_xml = lxml.etree.parse(handle) xml = amqp_xml.xpath('//amqp')[0] # Read in the codegen RabbitMQ Extension XML file with open(CODEGEN_DIR + 'extensions.xml', 'r') as handle: rabbitmq_xml = lxml.etree.parse(handle) rabbitmq = rabbitmq_xml.xpath('//rabbitmq')[0] # Start the output output = ['''"""%s Auto-generated AMQP Support Module WARNING: DO NOT EDIT. To Generate run tools/codegen.py """ __since__ = '%s' import struct import warnings from pamqp import decode, encode ''' % (CODEGEN_OUTPUT.split('/')[-1], datetime.date.today().isoformat())] new_line() # AMQP Version Header comment('AMQP Protocol Version') new_line('VERSION = (%i, %i, %i)' % ( amqp['major-version'], amqp['minor-version'], amqp['revision'])) new_line() # Defaults comment('RabbitMQ Defaults') new_line("DEFAULT_HOST = 'localhost'") new_line('DEFAULT_PORT = %i' % amqp['port']) new_line("DEFAULT_USER = 'guest'") new_line("DEFAULT_PASS = 'guest'") new_line("DEFAULT_VHOST = '/'") new_line() # Constant comment('AMQP Constants') for constant in amqp['constants']: if 'class' not in constant: # Look to see if documented & if so, provide the doc as a comment doc = get_documentation({'constant': constant['name'].lower()}) if doc: comment(doc) new_line('%s = %i' % (dashify(constant['name']), constant['value'])) new_line() comment('Not included in the spec XML or JSON files.') new_line('FRAME_MAX_SIZE = 131072') new_line() # Data types data_types = [] domains = [] for domain, data_type in amqp['domains']: if domain == data_type: data_types.append(" '%s'," % domain) else: doc = get_documentation({'domain': domain}) if doc: comments = get_comments(doc, 18) for line in comments: domains.append(line) domains.append(" '%s': '%s'," % (domain, data_type)) comment('AMQP data types') data_types[0] = data_types[0].replace(' ', 'DATA_TYPES = [') data_types[-1] = data_types[-1].replace(',', ']') output += data_types new_line() comment('AMQP domains') domains[0] = domains[0].replace(' ', 'DOMAINS = {') domains[-1] = domains[-1].replace(',', '}') output += domains new_line() comment('Other constants') # Deprecation Warning AMQP_VERSION = ('-'.join([str(amqp['major-version']), str(amqp['minor-version']), str(amqp['revision'])])) DEPRECATION_WARNING = 'This command is deprecated in AMQP %s' % AMQP_VERSION new_line("DEPRECATION_WARNING = '%s'" % DEPRECATION_WARNING) new_line() # Prepend the content from the files specified for filename in PREPEND: with open(filename, 'r') as handle: content = handle.read() for line in content.split('\n'): new_line(line) # Warnings and Exceptions new_line() comment('AMQP Errors') errors = {} for constant in amqp['constants']: if 'class' in constant: class_name = classify(constant['name']) if constant['class'] == 'soft-error': extends = 'Warning' elif constant['class'] == 'hard-error': extends = 'Exception' else: raise ValueError('Unexpected class: %s', constant['class']) new_line('class AMQP%s(%s):' % (class_name, extends)) new_line(' """') # Look to see if documented & if so, provide the doc as a comment doc = get_documentation({'constant': constant['name'].lower()}) if doc: comment(doc, 4, '') else: if extends == 'Warning': new_line(' Undocumented AMQP Soft Error') else: new_line(' Undocumented AMQP Hard Error') new_line() new_line(' """') new_line(" name = '%s'" % constant['name']) new_line(' value = %i' % constant['value']) new_line() new_line() errors[constant['value']] = class_name # Error mapping to class error_lines = [] for error_code in errors.keys(): error_lines.append( ' %i: AMQP%s,' % (error_code, errors[error_code])) comment('AMQP Error code to class mapping') error_lines[0] = error_lines[0].replace(' ', 'ERRORS = {') error_lines[-1] = error_lines[-1].replace(',', '}') output += error_lines # Get the pamqp class list so we can sort it class_list = [] for amqp_class in amqp['classes']: if amqp_class['name'] not in CODEGEN_IGNORE_CLASSES: class_list.append(amqp_class['name']) # Sort them alphabetically # class_list.sort() new_line() comment('AMQP Classes and Methods') new_line() for class_name in class_list: indent = 4 # Get the class from our JSON file definition = get_class_definition(class_name, amqp['classes']) new_line() new_line('class %s(object):' % pep8_class_name(class_name)) doc = get_documentation({'class': class_name}) label = get_label({'class': class_name}) or 'Undefined label' if doc: new_line('"""' + label, indent) new_line() comment(doc, indent, '') new_line() new_line('"""', indent) new_line('__slots__ = []', indent) new_line() comment('AMQP Class Number and Mapping Index', indent) new_line('frame_id = %i' % definition['id'], indent) new_line('index = 0x%08X' % (definition['id'] << 16), indent) new_line() # We use this later down in methods to get method xml to look for stuff # that is not in the JSON spec file beyond docs class_xml = xml.xpath('//amqp/class[@name="%s"]' % class_name) # Build the list of methods methods = [] for method in definition['methods']: new_line('class %s(Frame):' % pep8_class_name(method['name']), indent) indent += 4 # No Confirm in AMQP spec if class_xml: doc = get_documentation({'class': class_name, 'method': method['name']}) label = get_label({'class': class_name, 'method': method['name']}) or 'Undefined label' if doc: new_line('"""%s' % label, indent) new_line() comment(doc, indent, '') new_line() new_line('"""', indent) # Get the method's XML node method_xml = None if class_xml: method_xml = class_xml[0].xpath('method[@name="%s"]' % method['name']) comment('AMQP Method Number and Mapping Index', indent) new_line('frame_id = %i' % method['id'], indent) index_value = definition['id'] << 16 | method['id'] new_line('index = 0x%08X' % index_value, indent) new_line("name = '%s.%s'" % (pep8_class_name(class_name), pep8_class_name(method['name'])), indent) # Add an attribute that signifies if it's a sync command new_line() comment('Specifies if this is a synchronous AMQP method', indent) new_line('synchronous = %s' % method.get('synchronous', False), indent) # Add an attribute that signifies if it's a sync command if method.get('synchronous'): responses = [] if method_xml: for response in method_xml[0].iter('response'): response_name = "'%s.%s'" %\ (pep8_class_name(class_name), pep8_class_name(response.attrib['name'])) responses.append(response_name) if not responses: responses.append("'%s.%sOk'" % (pep8_class_name(class_name), pep8_class_name(method['name']))) new_line() comment('Valid responses to this method', indent) new_line('valid_responses = [%s]' % ', '.join(responses), indent) new_line() arguments = [] type_keyword = False for argument in method['arguments']: name = argument_name(argument['name']) if name == 'type' and class_name == 'exchange': name = 'exchange_type' type_keyword = True arguments.append("'%s'," % name) if arguments: comment('AMQP Method Attributes', indent) arguments[-1] = arguments[-1].replace(',', ']') new_line('__slots__ = [' + arguments.pop(0), indent) for line in arguments: new_line(line, indent + 13) new_line() if method['arguments']: comment('Class Attribute Types', indent) for argument in method['arguments']: name = argument_name(argument['name']) if name == 'type' and class_name == 'exchange': name = 'exchange_type' new_line("_%s = '%s'" % (name, get_argument_type(argument)), indent) new_line() # Function definition arguments = copy.deepcopy(method['arguments']) for offset in range(0, len(arguments)): if arguments[offset]['name'] == 'type' and \ class_name == 'exchange': arguments[offset]['name'] = 'exchange_type' if arguments: new_function('__init__', arguments, indent) indent += 4 new_line('"""Initialize the %s.%s class' % (pep8_class_name(class_name), pep8_class_name(method['name'])), indent) if type_keyword: new_line() new_line('Note that the AMQP type argument is referred to as ' '"%s_type" ' % class_name, indent) new_line('to not conflict with the Python type keyword.', indent) # List the arguments in the docblock new_line() for argument in method['arguments']: name = argument_name(argument['name']) if name == 'type' and class_name == 'exchange': name = 'exchange_type' label = get_label({'class': class_name, 'method': method['name'], 'field': argument['name']}) if label: new_line(':param %s %s: %s' % (get_argument_type_doc(argument), name, label), indent, indent + 4) else: new_line( ':param %s %s:' % ( get_argument_type_doc(argument), argument['name']), indent, indent + 4) # Note the deprecation warning in the docblock if method_xml and 'deprecated' in method_xml[0].attrib and \ method_xml[0].attrib['deprecated']: deprecated = True new_line() new_line( '.. deprecated:: %s' % AMQP_VERSION, indent) new_line(DEPRECATION_WARNING, indent + 4) else: deprecated = False new_line() new_line('"""', indent) # Create assignments from the arguments to attributes of the object for argument in method['arguments']: name = argument_name(argument['name']) if name == 'type' and class_name == 'exchange': name = 'exchange_type' doc = get_label({'class': class_name, 'method': method['name'], 'field': argument['name']}) if doc: comment(doc, indent) if (isinstance(argument.get('default-value'), dict) and not argument.get('default-value')): new_line('self.%s = %s or {}' % (name, name), indent) else: new_line('self.%s = %s' % (name, name), indent) new_line() # Check if we're deprecated and warn if so if deprecated: comment(DEPRECATION_WARNING, indent) new_line('warnings.warn(DEPRECATION_WARNING, ' 'category=DeprecationWarning)', indent) new_line() # End of function indent -= 4 # End of class indent -= 4 if 'properties' in definition and definition['properties']: new_line('class Properties(PropertiesBase):', indent) indent += 4 comment('"""Content Properties"""', indent, '') new_line() new_line("name = '%s.Properties'" % pep8_class_name(class_name), indent) new_line() new_line("__slots__ = ['%s'," % argument_name(definition['properties'][0]['name']), indent) for argument in definition['properties'][1:-1]: name = argument_name(argument['name']) if name == 'type': name = 'message_type' new_line("'%s'," % name, indent + 13) new_line("'%s']" % argument_name(definition['properties'][-1]['name']), indent + 13) new_line() comment('Flag Values', indent) flag_value = 15 new_line("flags = {'%s': %i," % (argument_name(definition['properties'][0]['name']), 1 << flag_value), indent) for argument in definition['properties'][1:-1]: name = argument_name(argument['name']) if name == 'type': name = 'message_type' flag_value -= 1 new_line("'%s': %i," % (name, 1 << flag_value), indent + 9), flag_value -= 1 new_line("'%s': %i}" % (argument_name(definition['properties'][-1]['name']), 1 << flag_value), indent + 9) new_line() comment('Class Attribute Types', indent) for argument in definition['properties']: name = argument_name(argument['name']) if name == 'type': name = 'message_type' new_line("_%s = '%s'" % (name, get_argument_type(argument)), indent) new_line() new_line('frame_id = %i' % definition['id'], indent) new_line('index = 0x%04X' % definition['id'], indent) new_line() # Function definition properties = copy.deepcopy(definition['properties']) for offset in range(0, len(properties)): if properties[offset]['name'] == 'type': properties[offset]['name'] = 'message_type' new_function('__init__', properties, indent) indent += 4 new_line('"""Initialize the %s.Properties class' % pep8_class_name(class_name), indent) new_line() new_line('Note that the AMQP property type is named message_type as ' 'to ', indent) new_line('not conflict with the Python type keyword', indent) # List the arguments in the docblock new_line() for argument in definition['properties']: name = argument_name(argument['name']) if name == 'type': name = 'message_type' label = get_label({'class': class_name, 'field': argument['name']}) if label: line = ':param %s %s: %s' % (get_argument_type_doc(argument), name, label or None) new_line(line.strip(), indent) new_line() new_line('"""', indent) # Create assignments from the arguments to attributes of the object for argument in definition['properties']: name = argument_name(argument['name']) if name == 'type': name = 'message_type' doc = get_label({'class': class_name, 'field': argument['name']}) if doc: comment(doc, indent) new_line('self.%s = %s' % (name, name), indent) new_line() # End of function indent -= 4 new_line() comment('AMQP Class.Method Index Mapping') mapping = [] for amqp_class in amqp['classes']: if amqp_class['name'] not in CODEGEN_IGNORE_CLASSES: for method in amqp_class['methods']: key = amqp_class['id'] << 16 | method['id'] mapping.append((' 0x%08X: %s.%s,' % (key, pep8_class_name(amqp_class['name']), pep8_class_name(method['name'])))) mapping[0] = mapping[0].replace(' ', 'INDEX_MAPPING = {') mapping[-1] = mapping[-1].replace(',', '}') output += mapping new_line() # Spit out the file output_string = '\n'.join(output) with open(CODEGEN_OUTPUT, 'w') as handle: handle.write(output_string)