os-api-ref-1.4.0/0000775000175000017500000000000013120043335014576 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/tox.ini0000664000175000017500000000177413120043152016117 0ustar jenkinsjenkins00000000000000[tox] minversion = 2.0 envlist = py27,pep8,docs skipsdist = True [testenv] setenv = VIRTUAL_ENV={envdir} BRANCH_NAME=master CLIENT_NAME=os-api-ref install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages} pip install -U {opts} {packages} deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt commands = python setup.py test --slowest --no-parallel --testr-args='{posargs}' [testenv:pep8] commands = flake8 {posargs} [testenv:venv] commands = {posargs} [testenv:cover] commands = python setup.py test --coverage --testr-args='{posargs}' [testenv:docs] commands = python setup.py build_sphinx [testenv:debug] commands = oslo_debug_helper {posargs} [flake8] # E123, E125 skipped as they are invalid PEP-8. show-source = True ignore = E123,E125,E129 builtins = _ exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build os-api-ref-1.4.0/doc/0000775000175000017500000000000013120043335015343 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/doc/source/0000775000175000017500000000000013120043335016643 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/doc/source/usage.rst0000664000175000017500000002433013120043152020500 0ustar jenkinsjenkins00000000000000Usage ===== ``os-api-ref`` is designed to be used inside of a sphinx tree that is devoted solely to the documentation of the API. Modify your ``source/conf.py`` file to include ``os_api_ref`` in the list of sphinx extensions. This extension assumes you are also using ``openstackdocstheme`` for some of the styling, and may not fully work if you are not. .. code-block:: python # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'os_api_ref', ] Stanzas ======= rest_method ----------- The ``rest_method`` stanza is a way to declare that a section is about a particular REST method. It takes the form of: .. code-block:: rst .. rest_method:: ``METHODNAME`` should be one of the commonly used REST methods or HTTP verbs. This stanza should be the first element in a ``section`` that has some descriptive title about the method. An example from the Nova documentation is: .. code-block:: rst List Servers ============ .. rest_method:: GET /v2.1/{tenant_id}/servers Lists IDs, names, and links for all servers. Servers contain a status attribute that indicates the current server state. You can filter on the server status when you complete a list servers request. The server status is returned in the response body. The possible server status values are: ... This is going to do a slightly unexpected transform where the ``rest_method`` is pivoted up and into the section title to produce an HTML line of the form: . The entire contents of the ``List Servers`` section will then be hidden by default, with a button to open it on demand. rest_parameters --------------- The ``rest_parameters`` stanza is a solution to the problem of tables in ``rst``. A REST API that uses JSON has a large number of structured parameters that include type, location (i.e. is this in the query, the header, the path, the body), whether or not this parameter is required, as well as the desire to provide a long description about each parameter. And, assuming some consistent modeling, that parameter will show up in multiple calls. A ``server_id`` used in the path is always going to have the same meaning. It is natural to want to display this data in a tabular way to show all these dimensions. However, tables in ``rst`` are quite cumbersome, and repeating the same data over and over again is error prone. The ``rest_parameters`` stanza solves this by having the inline markup be a yaml list of ``name: value`` pairs. ``name`` is the name of the parameter. ``value`` is the key to lookup the rest of the details for this parameter in a parameters file. In each method, there should be one ``rest_parameters`` stanza for the request, and another ``rest_parameters`` stanza for the response. .. code-block:: rst .. rest_parameters:: parameters.yaml - tenant_id: tenant_id - changes-since: changes-since - image: image_query - flavor: flavor_query - name: server_name_query - status: server_status_query - host: host_query - limit: limit - marker: marker And corresponding entries in ``parameters.yaml``: .. code-block:: yaml tenant_id: description: | The UUID of the tenant in a multi-tenancy cloud. in: path required: true type: string ... changes-since: description: | Filters the response by a date and time when the image last changed status. Use this query parameter to check for changes since a previous request rather than re-downloading and re-parsing the full status at each polling interval. If data has changed, the call returns only the items changed since the ``changes-since`` time. If data has not changed since the ``changes-since`` time, the call returns an empty list.\nTo enable you to keep track of changes, this filter also displays images that were deleted if the ``changes-since`` value specifies a date in the last 30 days. Items deleted more than 30 days ago might be returned, but it is not guaranteed. The date and time stamp format is `ISO 8601 `_: :: CCYY-MM-DDThh:mm:ss±hh:mm The ``±hh:mm`` value, if included, returns the time zone as an offset from UTC. For example, ``2015-08-27T09:49:58-05:00``. If you omit the time zone, the UTC time zone is assumed. in: query required: false type: string server_status_query: description: | Filters the response by a server status, as a string. For example, ``ACTIVE``. in: query required: false type: string Every ``rest_parameters`` stanza specifies the lookup file it will use. This gives you the freedom to decide how you would like to split up your parameters, ranging from a single global file, to a dedicated file for every stanza, or anywhere in between. parameters file format ---------------------- The parameters file is inspired by the OpenAPI (aka: Swagger) specification. The OpenAPI specification provides a property object which categorizes the parameters by type and describes how the parameter is used. The following fields exist for every entry: in where this parameter exists. One of ``header``, ``path``, ``query``, ``body``. description a free form description of the parameter. This can be multiline (if using the | or > tags in yaml), and supports ``rst`` format syntax. required whether this parameter is required or not. If ``required: false`` the parameter name will be rendered with an (Optional) keyword next to it type the javascript/json type of the field. one of ``boolean``, ``int``, ``float``, ``string``, ``array``, ``object``. min_version the microversion that this parameter was introduced at. Will render a *new in $version* stanza in the html output. max_version the last version that includes this parameter. Will render a *Deprecated in $version* stanza in the html output. rest_status_code ---------------- The ``rest_status_code`` stanza is how you can show what HTTP status codes your API uses and what they indicate. .. code-block:: rst .. rest_status_code:: This stanza should be the first element after the narrative section of the method description. An example from the Designate documentation is: .. code-block:: rst :emphasize-lines: 11-25 Create Zone =========== .. rest_method:: POST /v2/zones Create a zone Response codes -------------- .. rest_status_code:: success status.yaml - 200 - 100 - 201 .. rest_status_code:: error status.yaml - 405 - 403 - 401 - 400 - 500 - 409: duplicate_zone And corresponding entries in ``http-status.yaml``: .. code-block:: yaml 100: default: | An unusual code for an API 200: default: | Request was successful. 201: default: > Request has been fulfilled and new resource created. The ``Location`` header has the URL to the new item. 400: default: | Some content in the request was invalid zone_data_error: | Some of the data for the zone in the request is unavailable to the service. 401: default: | User must authenticate before making a request. 403: default: | Policy does not allow current user to do this operation. 405: default: | Method is not valid for this endpoint and resource. 409: default: | This resource has an action in progress that would conflict with this request. duplicate_zone: | There is already a zone with this name. 500: default: | Something went wrong with the service which prevents it from fulfilling the request. This RST example creates two HTML tables of response codes, one for success and one for errors. status file format ------------------ This is a simple yaml file, with a single object of status codes and the reasons that each would be used. Each status code **must** have a default entry in the status yaml file. The default entry is used in the ``rest_status_code`` stanza when a code is listed with no value or lookup key. There may be situations where the reason for a code may be different across endpoints, or a different message may be appropriate. In this case, adding a entry at the same level as the ``default`` and referencing that in the stanza like so: .. code-block:: yaml - 409: duplicate_zone This will override the default message with the newly defined one. You can get a copy of a starter status file from the os-api-ref repository, by downloading :download:`http-status.yaml `. rest_expand_all --------------- The ``rest_expand_all`` stanza is used to place a control in the document that will be a global Show / Hide for all sections. There are times when this is extremely nice to have. Including Sample Files ====================== To refer to a sample file in a ``rst`` file, use the ``rst`` directive, ``literalinclude``. Typically, the content sent or received is of type JSON, so the language role is set to javascript. The example immediately follows the parameter listing in the ``rst`` file. An example of an included Nova response sample file: .. code-block:: rst .. literalinclude:: ../../doc/api_samples/os-evacuate/server-evacuate-resp.json :language: javascript Runtime Warnings ================ The extension tries to help when it can by pointing out that something isn't matching up correctly. The following warnings are generated when issues are found: * parameters file is not found * parameters file is not valid yaml, i.e. missing colon after the name * a lookup value in the ``rst`` file is not found in the parameters file * the parameters file is not sorted as outlined in the rules below The sorting rules for parameters file is that first elements should be sorted by ``in``, going from earliest to latest processed. #. header #. path #. query #. body After that, the parameters should be sorted by name, lower case alpha numerically. The sort enforcement is because in large parameters files it helps prevent unintended duplicates. os-api-ref-1.4.0/doc/source/installation.rst0000664000175000017500000000027213120043152022074 0ustar jenkinsjenkins00000000000000Installation ============ At the command line:: $ pip install os-api-ref Or, if you have virtualenvwrapper installed:: $ mkvirtualenv os-api-ref $ pip install os-api-ref os-api-ref-1.4.0/doc/source/contributing.rst0000664000175000017500000000007713120043152022105 0ustar jenkinsjenkins00000000000000 Contributing ============ .. include:: ../../CONTRIBUTING.rst os-api-ref-1.4.0/doc/source/http-status.yaml0000664000175000017500000000371713120043152022034 0ustar jenkinsjenkins00000000000000 200: default: | Request was successful. image-data-200: | The service lists the image data in the response body. 201: default: | Request has been fulfilled and new resource created. 202: default: | Request is accepted, but processing may take some time. 203: default: | Returned information is not full set, but a subset. 204: default: | Request fulfilled but service does not return anything. 300: default: | The resource corresponds to more than one representation. 400: default: | Some content in the request was invalid. 401: default: | User must authenticate before making a request. 403: default: | Policy does not allow current user to do this operation. 404: default: | The requested resource could not be found. 405: default: | Method is not valid for this endpoint and resource. 409: default: | This resource has an action in progress that would conflict with this request. 413: default: | This operation cannot be completed. image-data-413: | The payload cannot be accepted. Possible causes include: * The backend storage is full. * This request added to your existing image data exceeds your total storage quota for images. * The image payload submitted with this request exceeds the maximum allowable image size. 415: default: | The entity of the request is in a format not supported by the requested resource for the method. 500: default: | Something went wrong with the service which prevents it from fulfilling the request. 501: default: | The service does not have the functionality required to fulfill this request. 503: default: | The service cannot handle the request right now. os-api-ref-1.4.0/doc/source/index.rst0000664000175000017500000000101713120043152020500 0ustar jenkinsjenkins00000000000000.. os-api-ref documentation master file, created by sphinx-quickstart on Tue Jul 9 22:26:36 2013. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. ============================================== Welcome to os-api-ref developer documentation! ============================================== .. toctree:: :maxdepth: 1 installation usage contributing Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` os-api-ref-1.4.0/doc/source/conf.py0000775000175000017500000000457613120043153020157 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys sys.path.insert(0, os.path.abspath('../..')) # -- General configuration ---------------------------------------------------- # 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.intersphinx', 'oslosphinx' ] # autodoc generation is a bit aggressive and a nuisance when doing heavy # text edit cycles. # execute "export SPHINX_DEBUG=1" in your terminal to disable # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = u'os-api-ref' copyright = u'2016, The contributors' # 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 # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. # html_theme_path = ["."] # html_theme = '_theme' # html_static_path = ['static'] # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass # [howto/manual]). latex_documents = [ ('index', '%s.tex' % project, u'%s Documentation' % project, u'OpenStack Foundation', 'manual'), ] # Example configuration for intersphinx: refer to the Python standard library. #intersphinx_mapping = {'http://docs.python.org/': None} os-api-ref-1.4.0/test-requirements.txt0000664000175000017500000000073113120043152021035 0ustar jenkinsjenkins00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0 coverage!=4.4,>=4.0 # Apache-2.0 python-subunit>=0.0.18 # Apache-2.0/BSD oslosphinx>=4.7.0 # Apache-2.0 testrepository>=0.0.18 # Apache-2.0/BSD testtools>=1.4.0 # MIT sphinx-testing # BSD License beautifulsoup4 # MIT os-api-ref-1.4.0/setup.py0000664000175000017500000000200613120043152016303 0ustar jenkinsjenkins00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT import setuptools # In python < 2.7.4, a lazy loading of package `pbr` will break # setuptools if some other modules registered functions in `atexit`. # solution from: http://bugs.python.org/issue15881#msg170215 try: import multiprocessing # noqa except ImportError: pass setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) os-api-ref-1.4.0/babel.cfg0000664000175000017500000000002113120043152016312 0ustar jenkinsjenkins00000000000000[python: **.py] os-api-ref-1.4.0/os_api_ref.egg-info/0000775000175000017500000000000013120043335020376 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref.egg-info/SOURCES.txt0000664000175000017500000000305413120043335022264 0ustar jenkinsjenkins00000000000000.coveragerc .mailmap .testr.conf AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE MANIFEST.in README.rst RELEASING.rst TESTS.rst babel.cfg requirements.txt setup.cfg setup.py test-requirements.txt tox.ini doc/source/conf.py doc/source/contributing.rst doc/source/http-status.yaml doc/source/index.rst doc/source/installation.rst doc/source/usage.rst os_api_ref/__init__.py os_api_ref/http_codes.py os_api_ref.egg-info/PKG-INFO os_api_ref.egg-info/SOURCES.txt os_api_ref.egg-info/dependency_links.txt os_api_ref.egg-info/not-zip-safe os_api_ref.egg-info/pbr.json os_api_ref.egg-info/requires.txt os_api_ref.egg-info/top_level.txt os_api_ref/assets/api-site.css os_api_ref/assets/api-site.js os_api_ref/assets/combobox.js os_api_ref/assets/glyphicons-halflings-regular.ttf os_api_ref/assets/glyphicons-halflings-regular.woff os_api_ref/tests/__init__.py os_api_ref/tests/base.py os_api_ref/tests/test_basic_example.py os_api_ref/tests/test_microversions.py os_api_ref/tests/test_os_api_ref.py os_api_ref/tests/test_warnings.py os_api_ref/tests/examples/basic/conf.py os_api_ref/tests/examples/basic/index.rst os_api_ref/tests/examples/basic/parameters.yaml os_api_ref/tests/examples/basic/status.yaml os_api_ref/tests/examples/microversions/conf.py os_api_ref/tests/examples/microversions/index.rst os_api_ref/tests/examples/microversions/parameters.yaml os_api_ref/tests/examples/warnings/conf.py os_api_ref/tests/examples/warnings/empty_parameters_file.yaml os_api_ref/tests/examples/warnings/index.rst os_api_ref/tests/examples/warnings/parameters.yaml tools/tox_install.shos-api-ref-1.4.0/os_api_ref.egg-info/not-zip-safe0000664000175000017500000000000113120043334022623 0ustar jenkinsjenkins00000000000000 os-api-ref-1.4.0/os_api_ref.egg-info/top_level.txt0000664000175000017500000000001313120043334023121 0ustar jenkinsjenkins00000000000000os_api_ref os-api-ref-1.4.0/os_api_ref.egg-info/PKG-INFO0000664000175000017500000001303413120043334021473 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: os-api-ref Version: 1.4.0 Summary: Sphinx Extensions to support API reference sites in OpenStack Home-page: http://docs.openstack.org/developer/os-api-ref Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/badges/os-api-ref.svg :target: http://governance.openstack.org/reference/tags/index.html .. Change things from this point on os-api-ref ========== Sphinx Extensions to support API reference sites in OpenStack This project is a collection of sphinx stanzas that assist in building an API Reference site for an OpenStack project in RST. RST is great for unstructured English, but displaying semi structured (and repetitive) data in tables is not its strength. This provides tooling to insert semi-structured data describing request and response parameters and status or error messages, and turn those into nice tables. The project also includes a set of styling (and javascript) that is expected to layer on top of a Sphinx theme base. This addition provides a nice set of collapsing sections for REST methods and javascript controls to expand / collapse all sections. Features -------- * Sphinx stanza ``rest_method`` describing the method and resource for a REST API call. Lets authors write simply and also gives readers a clean way to scan all methods then click a button to get more information about a method. * Sphinx stanza ``rest_parameters`` used to insert semi-structured data into the RST files describing the parameters users can send with the request. The stanza points to a structured YAML file, ``parameters.yaml``. * Sphinx stanza ``rest_status_code`` used to insert pointers to error or status codes returned by the service. Points to a structured YAML file, ``http_codes.yaml``. TODO ---- A list, in no particular order, of things we should do in this project. If you would like to contribute to any of these please show up in ``#openstack-dev`` on IRC and ask for ``sdague`` or ``mugsie`` to discuss or send an email to the openstack-dev@lists.openstack.org list with [api] in the subject line. * Enhance documentation with more examples and best practices * Testing for the code * ``max_microversion`` parameter support - so that we automatically tag parameters that have been removed * Make a microversion selector, so that you can get a version of the api-ref that hides all microversion elements beyond your selected version (this one is going to be a bit of complex javascript), in progress. Potential ideas ~~~~~~~~~~~~~~~ These aren't even quite todos, but just ideas about things that might be useful. * ``.. literalinclude`` is good for API samples files to be included, but should we have more markup that includes the full ``REST /URL`` as well. Sphinx stanzas -------------- **rest_method**: Enter the REST method, such as GET, PUT, POST, DELETE, followed by the resource (not including an endpoint) for the call. For example:: .. rest_method:: PUT /v2/images/{image_id}/file **rest_parameters**: Enter a reference to a ``parameters.yaml`` file and indicate which parameter you want to document. For example:: .. rest_parameters:: images-parameters.yaml - Content-type: Content-Type-data - image_id: image_id-in-path Where the ``images-parameters.yaml`` file contains pointers named ``Content-type`` and ``image_id`` and descriptions for each. **rest_status_code**: Enter a reference to a ``http-status.yaml`` file and indicate which errors or status codes you want to document. You can also add a pointer to more precise descriptions for each code. For example:: .. rest_status_code:: success http-codes.yaml - 204 .. rest_status_code:: error http-codes.yaml - 400: informal - 401 - 403 - 404 - 409 - 410: image-data-410 - 413: image-data-413 - 415: image-data-415 - 500: informal - 503: image-data-503 * Free software: Apache license * Documentation: http://docs.openstack.org/developer/os-api-ref * Source: http://git.openstack.org/cgit/openstack/os-api-ref Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 os-api-ref-1.4.0/os_api_ref.egg-info/requires.txt0000664000175000017500000000013513120043334022774 0ustar jenkinsjenkins00000000000000pbr!=2.1.0,>=2.0.0 PyYAML>=3.10.0 six>=1.9.0 sphinx!=1.6.1,>=1.5.1 openstackdocstheme>=1.5.0 os-api-ref-1.4.0/os_api_ref.egg-info/pbr.json0000664000175000017500000000005613120043334022054 0ustar jenkinsjenkins00000000000000{"git_version": "a67ed2f", "is_release": true}os-api-ref-1.4.0/os_api_ref.egg-info/dependency_links.txt0000664000175000017500000000000113120043334024443 0ustar jenkinsjenkins00000000000000 os-api-ref-1.4.0/.testr.conf0000664000175000017500000000047713120043152016671 0ustar jenkinsjenkins00000000000000[DEFAULT] test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ ${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION test_id_option=--load-list $IDFILE test_list_option=--list os-api-ref-1.4.0/AUTHORS0000664000175000017500000000135113120043334015645 0ustar jenkinsjenkins00000000000000Andreas Jaeger Anne Gentle Cao Xuan Hoang Daniel Gonzalez Dirk Mueller Dmitry Shachnev Flavio Percoco Graham Hayes Karen Bradshaw Monty Taylor Nam Nguyen Hoai Ondřej Nový Sean Dague Thomas Bechtold Tony Breeds Tony Xu Yuval Brik gengchc2 ricolin shashi.kant tengqm os-api-ref-1.4.0/LICENSE0000664000175000017500000002363713120043152015613 0ustar jenkinsjenkins00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. os-api-ref-1.4.0/MANIFEST.in0000664000175000017500000000013613120043152016331 0ustar jenkinsjenkins00000000000000include AUTHORS include ChangeLog exclude .gitignore exclude .gitreview global-exclude *.pyc os-api-ref-1.4.0/.mailmap0000664000175000017500000000013113120043152016207 0ustar jenkinsjenkins00000000000000# Format is: # # os-api-ref-1.4.0/README.rst0000664000175000017500000000757013120043152016273 0ustar jenkinsjenkins00000000000000======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/badges/os-api-ref.svg :target: http://governance.openstack.org/reference/tags/index.html .. Change things from this point on os-api-ref ========== Sphinx Extensions to support API reference sites in OpenStack This project is a collection of sphinx stanzas that assist in building an API Reference site for an OpenStack project in RST. RST is great for unstructured English, but displaying semi structured (and repetitive) data in tables is not its strength. This provides tooling to insert semi-structured data describing request and response parameters and status or error messages, and turn those into nice tables. The project also includes a set of styling (and javascript) that is expected to layer on top of a Sphinx theme base. This addition provides a nice set of collapsing sections for REST methods and javascript controls to expand / collapse all sections. Features -------- * Sphinx stanza ``rest_method`` describing the method and resource for a REST API call. Lets authors write simply and also gives readers a clean way to scan all methods then click a button to get more information about a method. * Sphinx stanza ``rest_parameters`` used to insert semi-structured data into the RST files describing the parameters users can send with the request. The stanza points to a structured YAML file, ``parameters.yaml``. * Sphinx stanza ``rest_status_code`` used to insert pointers to error or status codes returned by the service. Points to a structured YAML file, ``http_codes.yaml``. TODO ---- A list, in no particular order, of things we should do in this project. If you would like to contribute to any of these please show up in ``#openstack-dev`` on IRC and ask for ``sdague`` or ``mugsie`` to discuss or send an email to the openstack-dev@lists.openstack.org list with [api] in the subject line. * Enhance documentation with more examples and best practices * Testing for the code * ``max_microversion`` parameter support - so that we automatically tag parameters that have been removed * Make a microversion selector, so that you can get a version of the api-ref that hides all microversion elements beyond your selected version (this one is going to be a bit of complex javascript), in progress. Potential ideas ~~~~~~~~~~~~~~~ These aren't even quite todos, but just ideas about things that might be useful. * ``.. literalinclude`` is good for API samples files to be included, but should we have more markup that includes the full ``REST /URL`` as well. Sphinx stanzas -------------- **rest_method**: Enter the REST method, such as GET, PUT, POST, DELETE, followed by the resource (not including an endpoint) for the call. For example:: .. rest_method:: PUT /v2/images/{image_id}/file **rest_parameters**: Enter a reference to a ``parameters.yaml`` file and indicate which parameter you want to document. For example:: .. rest_parameters:: images-parameters.yaml - Content-type: Content-Type-data - image_id: image_id-in-path Where the ``images-parameters.yaml`` file contains pointers named ``Content-type`` and ``image_id`` and descriptions for each. **rest_status_code**: Enter a reference to a ``http-status.yaml`` file and indicate which errors or status codes you want to document. You can also add a pointer to more precise descriptions for each code. For example:: .. rest_status_code:: success http-codes.yaml - 204 .. rest_status_code:: error http-codes.yaml - 400: informal - 401 - 403 - 404 - 409 - 410: image-data-410 - 413: image-data-413 - 415: image-data-415 - 500: informal - 503: image-data-503 * Free software: Apache license * Documentation: http://docs.openstack.org/developer/os-api-ref * Source: http://git.openstack.org/cgit/openstack/os-api-ref os-api-ref-1.4.0/os_api_ref/0000775000175000017500000000000013120043335016704 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref/__init__.py0000664000175000017500000006073013120043153021021 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from collections import OrderedDict import os import re from docutils import nodes from docutils.parsers.rst.directives.tables import Table from docutils.statemachine import ViewList import pbr.version from sphinx.util.compat import Directive from sphinx.util.osutil import copyfile import yaml from os_api_ref.http_codes import http_code from os_api_ref.http_codes import http_code_html from os_api_ref.http_codes import HTTPResponseCodeDirective __version__ = pbr.version.VersionInfo( 'os_api_ref').version_string() # This is to allow for a graceful swap from oslosphinx to openstackdocstheme THEME = 'openstackdocstheme' """This provides a sphinx extension able to create the HTML needed for the api-ref website. It contains 2 new stanzas. .. rest_method:: GET /foo/bar Which is designed to be used as the first stanza in a new section to state that section is about that REST method. During processing the rest stanza will be reparented to be before the section in question, and used as a show/hide selector for it's details. .. rest_parameters:: file.yaml - name1: name_in_file1 - name2: name_in_file2 - name3: name_in_file3 Which is designed to build structured tables for either response or request parameters. The stanza takes a value which is a file to lookup details about the parameters in question. The contents of the stanza are a yaml list of key / value pairs. The key is the name of the parameter to be shown in the table. The value is the key in the file.yaml where all other metadata about the parameter will be extracted. This allows for reusing parameter definitions widely in API definitions, but still providing for control in both naming and ordering of parameters at every declaration. """ def ordered_load( stream, Loader=yaml.SafeLoader, object_pairs_hook=OrderedDict): """Load yaml as an ordered dict This allows us to inspect the order of the file on disk to make sure it was correct by our rules. """ class OrderedLoader(Loader): pass def construct_mapping(loader, node): loader.flatten_mapping(node) return object_pairs_hook(loader.construct_pairs(node)) OrderedLoader.add_constructor( yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, construct_mapping) # for parameters.yaml we treat numbers (especially version # numbers) as strings. So that microversion specification of 2.20 # and 2.2 don't get confused. OrderedLoader.add_constructor( u'tag:yaml.org,2002:float', yaml.constructor.SafeConstructor.construct_yaml_str) return yaml.load(stream, OrderedLoader) class rest_method(nodes.Part, nodes.Element): """Node for rest_method stanza Because we need to insert very specific HTML at the final stage of processing, the rest_method stanza needs a custom node type. This lets us accumulate the relevant data into this node, during parsing, but not turn it into known sphinx types (lists, tables, sections). Then, during the final build phase we transform directly to the html that we want. NOTE: this means we error trying to build latex or man pages for these stanza types right now. This is all fixable if we add an output formatter for this node type, but it's not yet a priority. Contributions welcomed. """ pass class rest_expand_all(nodes.Part, nodes.Element): """A node placeholder for the expand all button. This is a node that we can insert into the doctree which on final render can be converted to the custom HTML we need for the expand all button. It is automatically inserted at the top of the page for API ref documents. """ pass class RestExpandAllDirective(Directive): # This tells sphinx that the directive will need to generate # content during the final build phase. has_content = True def run(self): app = self.state.document.settings.env.app node = rest_expand_all() max_ver = app.config.os_api_ref_max_microversion min_ver = app.config.os_api_ref_min_microversion releases = app.config.os_api_ref_release_microversions node['major'] = None try: if max_ver.split('.')[0] == min_ver.split('.')[0]: node['max_ver'] = int(max_ver.split('.')[1]) node['min_ver'] = int(min_ver.split('.')[1]) node['major'] = int(max_ver.split('.')[0]) node['releases'] = releases except ValueError: # TODO(sdague): warn that we're ignoring this all pass except IndexError: pass return [node] class RestMethodDirective(Directive): # this enables content in the directive has_content = True @staticmethod def find_param(content, name): for line in content: if ("%s: " % name) in line: _, value = line.split(': ') return value.rstrip().lstrip() return None def run(self): lineno = self.state_machine.abs_line_number() target = nodes.target() section = nodes.section(classes=["detail-control"]) # env = self.state.document.settings.env # env.app.info("Parent %s" % self.state.parent.attributes) node = rest_method() # TODO(sdague): this is a super simplistic parser, should be # more robust. method, sep, url = self.content[0].partition(' ') node['min_version'] = self.find_param(self.content, 'min_version') node['max_version'] = self.find_param(self.content, 'max_version') node['method'] = method node['url'] = url # Extract the path parameters from the url env = self.state.document.settings.env env.path_params = [] env.path_params = re.findall("{[a-zA-Z][a-zA-Z_0-9]*}", url) node['target'] = self.state.parent.attributes['ids'][0] node['css_classes'] = "" if node['min_version']: node['css_classes'] += "rp_min_ver_%s " % ( str(node['min_version']).replace('.', '_')) if node['max_version']: node['css_classes'] += "rp_max_ver_%s " % ( str(node['max_version']).replace('.', '_')) # We need to build a temporary target that we can replace # later in the processing to get the TOC to resolve correctly. temp_target = "%s-selector" % node['target'] target = nodes.target(ids=[temp_target]) self.state.add_target(temp_target, '', target, lineno) section += node return [target, section] # cache for file -> yaml so we only do the load and check of a yaml # file once during a sphinx processing run. YAML_CACHE = {} class RestParametersDirective(Table): headers = ["Name", "In", "Type", "Description"] def _load_param_file(self, fpath): global YAML_CACHE if fpath in YAML_CACHE: return YAML_CACHE[fpath] lookup = {} # self.app.info("Fpath: %s" % fpath) try: with open(fpath, 'r') as stream: lookup = ordered_load(stream) except IOError: self.app.warn( "Parameters file %s not found" % fpath, (self.env.docname, None)) return except yaml.YAMLError as exc: self.app.warn(exc) raise if lookup: self._check_yaml_sorting(fpath, lookup) else: self.app.warn( "Parameters file is empty %s" % fpath, (self.env.docname, None)) return YAML_CACHE[fpath] = lookup return lookup def _check_yaml_sorting(self, fpath, yaml_data): """check yaml sorting Assuming we got an ordered dict, we iterate through it basically doing a gnome sort test (https://en.wikipedia.org/wiki/Gnome_sort) and ensure the item we are looking at is > the last item we saw. This is done at the section level first, so we're grouped, then alphabetically by lower case name within a section. Every time there is a mismatch we raise an warn message. """ sections = {"header": 1, "path": 2, "query": 3, "body": 4} last = None for key, value in yaml_data.items(): # use of an invalid 'in' value if value['in'] not in sections: self.app.warn( "``%s`` is not a valid value for 'in' (must be one of: %s)" ". (see ``%s``)" % ( value['in'], ", ".join(sorted(sections.keys())), key) ) continue if last is None: last = (key, value) continue # ensure that sections only go up current_section = value['in'] last_section = last[1]['in'] if sections[current_section] < sections[last_section]: self.app.warn( "Section out of order. All parameters in section ``%s`` " "should be after section ``%s``. (see ``%s``)" % ( last_section, current_section, last[0])) if (sections[value['in']] == sections[last[1]['in']] and key.lower() < last[0].lower()): self.app.warn( "Parameters out of order ``%s`` should be after ``%s``" % ( last[0], key)) last = (key, value) def yaml_from_file(self, fpath): """Collect Parameter stanzas from inline + file. This allows use to reference an external file for the actual parameter definitions. """ lookup = self._load_param_file(fpath) if not lookup: return content = "\n".join(self.content) parsed = yaml.safe_load(content) # self.app.info("Params loaded is %s" % parsed) # self.app.info("Lookup table looks like %s" % lookup) new_content = list() for paramlist in parsed: if not isinstance(paramlist, dict): self.app.warn( ("Invalid parameter definition ``%s``. Expected " "format: ``name: reference``. " " Skipping." % paramlist), (self.state_machine.node.source, self.state_machine.node.line)) continue for name, ref in paramlist.items(): if ref in lookup: new_content.append((name, lookup[ref])) else: # TODO(sdague): this provides a kind of confusing # error message because app.warn isn't meant to be # used this way, however it does provide a way to # track down where the parameters list is that is # wrong. So it's good enough for now. self.app.warn( ("No field definition for ``%s`` found in ``%s``. " " Skipping." % (ref, fpath)), (self.state_machine.node.source, self.state_machine.node.line)) # Check for path params in stanza for i, param in enumerate(self.env.path_params): if (param.rstrip('}').lstrip('{')) == name: del self.env.path_params[i] break else: continue if len(self.env.path_params) is not 0: # Warn that path parameters are not set in rest_parameter # stanza and will not appear in the generated table. for param in self.env.path_params: self.app.warn( ("No path parameter ``%s`` found in rest_parameter" " stanza.\n" % param.rstrip('}').lstrip('{')), (self.state_machine.node.source, self.state_machine.node.line)) # self.app.info("New content %s" % new_content) self.yaml = new_content def run(self): self.env = self.state.document.settings.env self.app = self.env.app # Make sure we have some content, which should be yaml that # defines some parameters. if not self.content: error = self.state_machine.reporter.error( 'No parameters defined', nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error] if not len(self.arguments) >= 1: error = self.state_machine.reporter.error( 'No reference file defined', nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error] # NOTE(sdague): it's important that we pop the arg otherwise # we end up putting the filename as the table caption. rel_fpath, fpath = self.env.relfn2path(self.arguments.pop()) self.yaml_file = fpath self.yaml_from_file(self.yaml_file) self.max_cols = len(self.headers) # TODO(sdague): it would be good to dynamically set column # widths (or basically make the colwidth thing go away # entirely) self.options['widths'] = [20, 10, 10, 60] self.col_widths = self.get_column_widths(self.max_cols) if isinstance(self.col_widths, tuple): # In docutils 0.13.1, get_column_widths returns a (widths, # colwidths) tuple, where widths is a string (i.e. 'auto'). # See https://sourceforge.net/p/docutils/patches/120/. self.col_widths = self.col_widths[1] # Actually convert the yaml title, messages = self.make_title() # self.app.info("Title %s, messages %s" % (title, messages)) table_node = self.build_table() self.add_name(table_node) if title: table_node.insert(0, title) return [table_node] + messages def get_rows(self, table_data): rows = [] groups = [] trow = nodes.row() entry = nodes.entry() para = nodes.paragraph(text=unicode(table_data)) entry += para trow += entry rows.append(trow) return rows, groups # Add a column for a field. In order to have the RST inside # these fields get rendered, we need to use the # ViewList. Note, ViewList expects a list of lines, so chunk # up our content as a list to make it happy. def add_col(self, value): entry = nodes.entry() result = ViewList(value.split('\n')) self.state.nested_parse(result, 0, entry) return entry def show_no_yaml_error(self): trow = nodes.row(classes=["no_yaml"]) trow += self.add_col("No yaml found %s" % self.yaml_file) trow += self.add_col("") trow += self.add_col("") trow += self.add_col("") return trow def collect_rows(self): rows = [] groups = [] try: # self.app.info("Parsed content is: %s" % self.yaml) for key, values in self.yaml: min_version = values.get('min_version', '') max_version = values.get('max_version', '') desc = values.get('description', '') classes = [] if min_version: desc += ("\n\n**New in version %s**\n" % min_version) min_ver_css_name = ("rp_min_ver_" + str(min_version).replace('.', '_')) classes.append(min_ver_css_name) if max_version: desc += ("\n\n**Deprecated in version %s**\n" % max_version) max_ver_css_name = ("rp_max_ver_" + str(max_version).replace('.', '_')) classes.append(max_ver_css_name) trow = nodes.row(classes=classes) name = key if values.get('required', False) is False: name += " (Optional)" trow += self.add_col(name) trow += self.add_col(values.get('in')) trow += self.add_col(values.get('type')) trow += self.add_col(desc) rows.append(trow) except AttributeError as exc: if 'key' in locals(): self.app.warn("Failure on key: %s, values: %s. %s" % (key, values, exc)) else: rows.append(self.show_no_yaml_error()) return rows, groups def build_table(self): table = nodes.table() tgroup = nodes.tgroup(cols=len(self.headers)) table += tgroup # TODO(sdague): it would be really nice to figure out how not # to have this stanza, it kind of messes up all of the table # formatting because it doesn't let tables just be the right # size. tgroup.extend( nodes.colspec(colwidth=col_width, colname='c' + str(idx)) for idx, col_width in enumerate(self.col_widths) ) thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node row_node.extend(nodes.entry(h, nodes.paragraph(text=h)) for h in self.headers) tbody = nodes.tbody() tgroup += tbody rows, groups = self.collect_rows() tbody.extend(rows) table.extend(groups) return table def rest_method_html(self, node): tmpl = """
%(method)s
%(url)s

%(desc)s

""" node['url'] = node['url'].replace( '{', '{') node['url'] = node['url'].replace( '}', '}') self.body.append(tmpl % node) raise nodes.SkipNode def rest_expand_all_html(self, node): tmpl = """
%(extra_js)s
%(selector)s
""" node.setdefault('selector', "") node.setdefault('extra_js', "") if node['major']: node['selector'], node['extra_js'] = create_mv_selector(node) self.body.append(tmpl % node) raise nodes.SkipNode def create_mv_selector(node): mv_list = '' for x in range(node['min_ver'], node['max_ver'] + 1): mv_list += build_mv_item(node['major'], x, node['releases']) selector_tmpl = """
""" js_tmpl = """ """ selector_content = { 'mv_list': mv_list } js_content = { 'min': node['min_ver'], 'max': node['max_ver'] } return selector_tmpl % selector_content, js_tmpl % js_content def build_mv_item(major, micro, releases): version = "%d.%d" % (major, micro) if version in releases: return '' % ( version, version, releases[version].capitalize()) else: return '' % (version, version) def resolve_rest_references(app, doctree): for node in doctree.traverse(): if isinstance(node, rest_method): rest_node = node rest_method_section = node.parent rest_section = rest_method_section.parent gp = rest_section.parent # Added required classes to the top section rest_section.attributes['classes'].append('api-detail') rest_section.attributes['classes'].append('collapse') # Pop the title off the collapsed section title = rest_section.children.pop(0) rest_node['desc'] = title.children[0] # In order to get the links in the sidebar to be right, we # have to do some id flipping here late in the game. The # rest_method_section has basically had a dummy id up # until this point just to keep it from colliding with # it's parent. rest_section.attributes['ids'][0] = ( "%s-detail" % rest_section.attributes['ids'][0]) rest_method_section.attributes['ids'][0] = rest_node['target'] # Pop the overall section into it's grand parent, # right before where the current parent lives idx = gp.children.index(rest_section) rest_section.remove(rest_method_section) gp.insert(idx, rest_method_section) def copy_assets(app, exception): assets = ('api-site.css', 'api-site.js', 'combobox.js') fonts = ( 'glyphicons-halflings-regular.ttf', 'glyphicons-halflings-regular.woff' ) if app.builder.name != 'html' or exception: return app.info('Copying assets: %s' % ', '.join(assets)) app.info('Copying fonts: %s' % ', '.join(fonts)) for asset in assets: dest = os.path.join(app.builder.outdir, '_static', asset) source = os.path.abspath(os.path.dirname(__file__)) copyfile(os.path.join(source, 'assets', asset), dest) for font in fonts: dest = os.path.join(app.builder.outdir, '_static/fonts', font) source = os.path.abspath(os.path.dirname(__file__)) copyfile(os.path.join(source, 'assets', font), dest) def add_assets(app): app.add_stylesheet('api-site.css') app.add_javascript('api-site.js') app.add_javascript('combobox.js') def setup(app): # Add some config options around microversions app.add_config_value('os_api_ref_max_microversion', '', 'env') app.add_config_value('os_api_ref_min_microversion', '', 'env') app.add_config_value('os_api_ref_release_microversions', '', 'env') # TODO(sdague): if someone wants to support latex/pdf, or man page # generation using these stanzas, here is where you'd need to # specify content specific renderers. app.add_node(rest_method, html=(rest_method_html, None)) app.add_node(rest_expand_all, html=(rest_expand_all_html, None)) app.add_node(http_code, html=(http_code_html, None)) # This specifies all our directives that we're adding app.add_directive('rest_parameters', RestParametersDirective) app.add_directive('rest_method', RestMethodDirective) app.add_directive('rest_expand_all', RestExpandAllDirective) app.add_directive('rest_status_code', HTTPResponseCodeDirective) # The doctree-read hook is used do the slightly crazy doc # transformation that we do to get the rest_method document # structure. app.connect('doctree-read', resolve_rest_references) # Add all the static assets to our build during the early stage of building app.connect('builder-inited', add_assets) # This copies all the assets (css, js, fonts) over to the build # _static directory during final build. app.connect('build-finished', copy_assets) return {'version': __version__} os-api-ref-1.4.0/os_api_ref/tests/0000775000175000017500000000000013120043335020046 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref/tests/examples/0000775000175000017500000000000013120043335021664 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref/tests/examples/microversions/0000775000175000017500000000000013120043335024566 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref/tests/examples/microversions/parameters.yaml0000664000175000017500000000046413120043152027616 0ustar jenkinsjenkins00000000000000name: in: body required: true type: string description: | The name of things name2: in: body required: true type: string description: | The name of things min_version: 2.11 name3: in: body required: true type: string description: | The name of things max_version: 2.20os-api-ref-1.4.0/os_api_ref/tests/examples/microversions/index.rst0000664000175000017500000000050013120043152026417 0ustar jenkinsjenkins00000000000000.. rest_expand_all:: I am text, hear me roar! ============== List Servers ============== .. rest_method:: GET /servers .. rest_parameters:: parameters.yaml - name: name - name2: name2 - name3: name3 =========== List Tags =========== .. rest_method:: GET /tags min_version: 2.17 max_version: 2.19 os-api-ref-1.4.0/os_api_ref/tests/examples/microversions/conf.py0000664000175000017500000000221413120043153026062 0ustar jenkinsjenkins00000000000000# # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. import openstackdocstheme html_theme = 'openstackdocs' html_theme_path = [openstackdocstheme.get_html_theme_path()] html_theme_options = { "sidebar_mode": "toc", } extensions = [ 'os_api_ref', ] # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' os_api_ref_min_microversion = '2.1' os_api_ref_max_microversion = '2.30' os-api-ref-1.4.0/os_api_ref/tests/examples/warnings/0000775000175000017500000000000013120043335023514 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref/tests/examples/warnings/empty_parameters_file.yaml0000664000175000017500000000002713120043152030754 0ustar jenkinsjenkins00000000000000# Empty parameter file os-api-ref-1.4.0/os_api_ref/tests/examples/warnings/parameters.yaml0000664000175000017500000000064113120043152026541 0ustar jenkinsjenkins00000000000000# valid path parameter server_id: description: | ID for server. in: path required: true type: string # These are out of order, this should be a warning. name2: in: body required: false type: string description: | foo name: in: body required: true type: string description: | The name of things name_1: description: | name_1 is missing type field. in: body required: true os-api-ref-1.4.0/os_api_ref/tests/examples/warnings/index.rst0000664000175000017500000000174113120043152025355 0ustar jenkinsjenkins00000000000000.. rest_expand_all:: I am text, hear me roar! ============== List Servers ============== .. rest_method:: GET /servers .. rest_parameters:: parameters.yaml - name: name - name: lookup_key_name - name: name_1 - invalid_name No Parameters Specified ----------------------- .. rest_parameters:: parameters.yaml Empty File and Parameters Specified ----------------------------------- .. rest_parameters:: empty_parameters_file.yaml - name: name Nonexistent Parameter File -------------------------- .. rest_parameters:: no_parameters.yaml Check missing path parameters in stanza --------------------------------------- .. rest_method:: GET /server/{server_id}/{new_id}/{new_id2} .. rest_parameters:: parameters.yaml - server_id: server_id Check another missing path parameters in stanza ----------------------------------------------- .. rest_method:: GET /server/{b_id}/{c_id2}/{server_id} .. rest_parameters:: parameters.yaml - server_id: server_id os-api-ref-1.4.0/os_api_ref/tests/examples/warnings/conf.py0000664000175000017500000000210213120043153025004 0ustar jenkinsjenkins00000000000000# # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. import openstackdocstheme html_theme = 'openstackdocs' html_theme_path = [openstackdocstheme.get_html_theme_path()] html_theme_options = { "sidebar_mode": "toc", } extensions = [ 'os_api_ref', ] # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' os-api-ref-1.4.0/os_api_ref/tests/examples/basic/0000775000175000017500000000000013120043335022745 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref/tests/examples/basic/status.yaml0000664000175000017500000000144313120043152025153 0ustar jenkinsjenkins00000000000000################# # Success Codes # ################# 100: default: | An unusual code for an API 200: default: | Request was successful. 201: default: | Resource was created and is ready to use. ################# # Error Codes # ################# 400: default: | Some content in the request was invalid zone_data_error: | Some of the data for the 401: default: | User must authenticate before making a request 403: default: | Policy does not allow current user to do this operation. 405: default: | Method is not valid for this endpoint. 409: default: | This operation conflicted with another operation on this resource duplcate_zone: | There is already a zone with this name. 500: default: | Something went wrong inside the service. os-api-ref-1.4.0/os_api_ref/tests/examples/basic/parameters.yaml0000664000175000017500000000013113120043152025764 0ustar jenkinsjenkins00000000000000name: in: body required: true type: string description: | The name of things os-api-ref-1.4.0/os_api_ref/tests/examples/basic/index.rst0000664000175000017500000000061013120043152024600 0ustar jenkinsjenkins00000000000000.. rest_expand_all:: I am text, hear me roar! ============== List Servers ============== .. rest_method:: GET /servers .. rest_parameters:: parameters.yaml - name: name Response codes -------------- .. rest_status_code:: success status.yaml - 200 - 100 - 201 .. rest_status_code:: error status.yaml - 405 - 403 - 401 - 400 - 500 - 409: duplcate_zone os-api-ref-1.4.0/os_api_ref/tests/examples/basic/conf.py0000664000175000017500000000210213120043153024235 0ustar jenkinsjenkins00000000000000# # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. import openstackdocstheme html_theme = 'openstackdocs' html_theme_path = [openstackdocstheme.get_html_theme_path()] html_theme_options = { "sidebar_mode": "toc", } extensions = [ 'os_api_ref', ] # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' os-api-ref-1.4.0/os_api_ref/tests/test_basic_example.py0000664000175000017500000001155713120043152024261 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """ test_os_api_ref ---------------------------------- Tests for `os_api_ref` module. """ from bs4 import BeautifulSoup from sphinx_testing import with_app from os_api_ref.tests import base class TestBasicExample(base.TestCase): """Test basic rendering. This can be used to test that basic rendering works for these examples, so if someone breaks something we know. """ @with_app(buildername='html', srcdir=base.example_dir('basic'), copy_srcdir_to_tmpdir=True) def setUp(self, app, status, warning): super(TestBasicExample, self).setUp() self.app = app self.status = status self.warning = warning self.app.build() self.html = (app.outdir / 'index.html').read_text() self.soup = BeautifulSoup(self.html, 'html.parser') self.content = str(self.soup) def test_expand_all(self): """Do we get an expand all button like we expect.""" content = str(self.soup.find(id='expand-all')) example_button = ('') self.assertEqual( example_button, content) def test_rest_method(self): """Do we get a REST method call block""" # TODO(sdague): it probably would make sense to do this as a # whole template instead of parts. content = str(self.soup.find_all(class_='operation-grp')) self.assertIn( '', str(content)) self.assertIn( 'GET', str(content)) self.assertIn( '
/servers
', str(content)) self.assertIn( (''), str(content)) def test_parameters(self): """Do we get some parameters table""" table = """
Name In Type Description
name body string The name of things
""" self.assertIn(table, self.content) def test_rest_response(self): success_table = """table border="1" class="docutils"> Code Reason 200 - OK Request was successful. 100 - Continue An unusual code for an API 201 - Created Resource was created and is ready to use. """ error_table = """
Code Reason
405 - Method Not Allowed Method is not valid for this endpoint.
403 - Forbidden Policy does not allow current user to do this operation.
401 - Unauthorized User must authenticate before making a request
400 - Bad Request Some content in the request was invalid
500 - Internal Server Error Something went wrong inside the service.
409 - Conflict There is already a zone with this name.
""" self.assertIn(success_table, self.content) self.assertIn(error_table, self.content) os-api-ref-1.4.0/os_api_ref/tests/test_warnings.py0000664000175000017500000000703113120043153023306 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """ test_os_api_ref ---------------------------------- Tests for `os_api_ref` module. """ from bs4 import BeautifulSoup from sphinx_testing import with_app from os_api_ref.tests import base class TestWarnings(base.TestCase): """Test basic rendering. This can be used to test that basic rendering works for these examples, so if someone breaks something we know. """ @with_app(buildername='html', srcdir=base.example_dir('warnings'), copy_srcdir_to_tmpdir=True) def setUp(self, app, status, warning): super(TestWarnings, self).setUp() self.app = app self.app.build() self.status = status.getvalue() self.warning = warning.getvalue() self.html = (app.outdir / 'index.html').read_text() self.soup = BeautifulSoup(self.html, 'html.parser') self.content = str(self.soup) def test_out_of_order(self): """Do we get an out of order naming warning.""" self.assertIn( ("WARNING: Parameters out of order ``name2`` " "should be after ``name``"), self.warning) def test_missing_lookup_name(self): """Warning when missing a lookup key in parameter file.""" self.assertIn( ("WARNING: No field definition for ``lookup_key_name`` found in "), self.warning) def test_missing_field(self): """Warning when missing type field in parameter file.""" self.assertIn( ("WARNING: Failure on key: name, values: " + "OrderedDict([('description'," + " 'name_1 is missing type field.\\n'), ('in', 'body')," + " ('required', True)]). " + "'NoneType' object has no attribute 'split'"), self.warning) def test_invalid_parameter_definition(self): """Warning when parameter definition is invalid.""" self.assertIn( ("WARNING: Invalid parameter definition ``invalid_name``. " + "Expected format: ``name: reference``. "), self.warning) def test_empty_parameter_file(self): """Warning when parameter file exists but is empty.""" self.assertIn( ("WARNING: Parameters file is empty"), self.warning) def test_no_parameters_set(self): """Error when parameters are not set in rest_parameters stanza.""" self.assertIn( ("No parameters defined\n\n.." + " rest_parameters:: parameters.yaml"), self.warning) def test_parameter_file_not_exist(self): """Error when parameter file does not exist""" self.assertIn( ("No parameters defined\n\n.." + " rest_parameters:: no_parameters.yaml"), self.warning) def test_missing_path_parameter_in_stanza(self): """Warning when path param not found in rest_parameter stanza.""" self.assertIn( ("WARNING: No path parameter ``b_id`` found in" + " rest_parameter stanza.\n"), self.warning) os-api-ref-1.4.0/os_api_ref/tests/test_microversions.py0000664000175000017500000001036313120043152024361 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """ test_os_api_ref ---------------------------------- Tests for `os_api_ref` module. """ from bs4 import BeautifulSoup from sphinx_testing import with_app from os_api_ref.tests import base class TestMicroversions(base.TestCase): """Test basic rendering. This can be used to test that basic rendering works for these examples, so if someone breaks something we know. """ @with_app(buildername='html', srcdir=base.example_dir('microversions'), copy_srcdir_to_tmpdir=True) def setUp(self, app, status, warning): super(TestMicroversions, self).setUp() self.app = app self.app.build() self.status = status.getvalue() self.warning = warning.getvalue() self.html = (app.outdir / 'index.html').read_text() self.soup = BeautifulSoup(self.html, 'html.parser') self.content = str(self.soup) def test_rest_method(self): """Test that min / max mv css class attributes are set""" content = self.soup.find_all(class_='rp_min_ver_2_17') self.assertIn( '
', str(content[0])) content = self.soup.find_all(class_='rp_max_ver_2_19') self.assertIn( '
', str(content[0])) def test_parameters_table(self): """Test that min / max mv css class attributes are set in params""" table = """
Name In Type Description
name body string The name of things
name2 body string

The name of things

New in version 2.11

name3 body string

The name of things

Deprecated in version 2.20

""" # noqa self.assertIn(table, self.content) def test_mv_selector(self): button_selectors = '' # noqa self.assertIn(button_selectors, self.content) def test_js_declares(self): self.assertIn("os_max_mv = 30;", self.content) self.assertIn("os_min_mv = 1;", self.content) os-api-ref-1.4.0/os_api_ref/tests/base.py0000664000175000017500000000617313120043152021336 0ustar jenkinsjenkins00000000000000# Copyright 2010-2011 OpenStack Foundation # Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import os import fixtures import testtools def example_dir(name=""): return os.path.join(os.path.dirname(__file__), 'examples', name) _TRUE_VALUES = ('True', 'true', '1', 'yes') class OutputStreamCapture(fixtures.Fixture): """Capture output streams during tests. This fixture captures errant printing to stderr / stdout during the tests and lets us see those streams at the end of the test runs instead. Useful to see what was happening during failed tests. """ def setUp(self): super(OutputStreamCapture, self).setUp() if os.environ.get('OS_STDOUT_CAPTURE') in _TRUE_VALUES: self.out = self.useFixture(fixtures.StringStream('stdout')) self.useFixture( fixtures.MonkeyPatch('sys.stdout', self.out.stream)) if os.environ.get('OS_STDERR_CAPTURE') in _TRUE_VALUES: self.err = self.useFixture(fixtures.StringStream('stderr')) self.useFixture( fixtures.MonkeyPatch('sys.stderr', self.err.stream)) @property def stderr(self): return self.err._details["stderr"].as_text() @property def stdout(self): return self.out._details["stdout"].as_text() class Timeout(fixtures.Fixture): """Setup per test timeouts. In order to avoid test deadlocks we support setting up a test timeout parameter read from the environment. In almost all cases where the timeout is reached this means a deadlock. A class level TIMEOUT_SCALING_FACTOR also exists, which allows extremely long tests to specify they need more time. """ def __init__(self, timeout, scaling=1): super(Timeout, self).__init__() try: self.test_timeout = int(timeout) except ValueError: # If timeout value is invalid do not set a timeout. self.test_timeout = 0 if scaling >= 1: self.test_timeout *= scaling else: raise ValueError('scaling value must be >= 1') def setUp(self): super(Timeout, self).setUp() if self.test_timeout > 0: self.useFixture(fixtures.Timeout(self.test_timeout, gentle=True)) class TestCase(testtools.TestCase): """Test case base class for all unit tests.""" def setUp(self): """Run before each test method to initialize test environment.""" super(TestCase, self).setUp() self.useFixture(Timeout( os.environ.get('OS_TEST_TIMEOUT', 0))) self.useFixture(OutputStreamCapture()) os-api-ref-1.4.0/os_api_ref/tests/test_os_api_ref.py0000664000175000017500000000136313120043152023565 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """ test_os_api_ref ---------------------------------- Tests for `os_api_ref` module. """ from os_api_ref.tests import base class TestOs_api_ref(base.TestCase): def test_something(self): pass os-api-ref-1.4.0/os_api_ref/tests/__init__.py0000664000175000017500000000000013120043152022142 0ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref/assets/0000775000175000017500000000000013120043335020206 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/os_api_ref/assets/combobox.js0000664000175000017500000003201613120043152022353 0ustar jenkinsjenkins00000000000000/* ============================================================= * bootstrap-combobox.js v1.1.7 * ============================================================= * Copyright 2012 Daniel Farrell * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ============================================================ */ !function( $ ) { "use strict"; /* COMBOBOX PUBLIC CLASS DEFINITION * ================================ */ var Combobox = function ( element, options ) { this.options = $.extend({}, $.fn.combobox.defaults, options); this.template = this.options.template || this.template this.$source = $(element); this.$container = this.setup(); this.$element = this.$container.find('input[type=text]'); this.$target = this.$container.find('input[type=hidden]'); this.$button = this.$container.find('.dropdown-toggle'); this.$menu = $(this.options.menu).appendTo('body'); this.matcher = this.options.matcher || this.matcher; this.sorter = this.options.sorter || this.sorter; this.highlighter = this.options.highlighter || this.highlighter; this.shown = false; this.selected = false; this.refresh(); this.transferAttributes(); this.listen(); }; Combobox.prototype = { constructor: Combobox , setup: function () { var combobox = $(this.template()); this.$source.before(combobox); this.$source.hide(); return combobox; } , disable: function() { this.$element.prop('disabled', true); this.$button.attr('disabled', true); this.disabled = true; this.$container.addClass('combobox-disabled'); } , enable: function() { this.$element.prop('disabled', false); this.$button.attr('disabled', false); this.disabled = false; this.$container.removeClass('combobox-disabled'); } , parse: function () { var that = this , map = {} , source = [] , selected = false , selectedValue = ''; this.$source.find('option').each(function() { var option = $(this); if (option.val() === '') { that.options.placeholder = option.text(); return; } map[option.text()] = option.val(); source.push(option.text()); if (option.prop('selected')) { selected = option.text(); selectedValue = option.val(); } }) this.map = map; if (selected) { this.$element.val(selected); this.$target.val(selectedValue); this.$container.addClass('combobox-selected'); this.selected = true; } return source; } , transferAttributes: function() { this.options.placeholder = this.$source.attr('data-placeholder') || this.options.placeholder if(this.options.appendId !== "undefined") { this.$element.attr('id', this.$source.attr('id') + this.options.appendId); } this.$element.attr('placeholder', this.options.placeholder) this.$target.prop('name', this.$source.prop('name')) this.$target.val(this.$source.val()) this.$source.removeAttr('name') // Remove from source otherwise form will pass parameter twice. this.$element.attr('required', this.$source.attr('required')) this.$element.attr('rel', this.$source.attr('rel')) this.$element.attr('title', this.$source.attr('title')) this.$element.attr('class', this.$source.attr('class')) this.$element.attr('tabindex', this.$source.attr('tabindex')) this.$source.removeAttr('tabindex') if (this.$source.attr('disabled')!==undefined) this.disable(); } , select: function () { var val = this.$menu.find('.active').attr('data-value'); this.$element.val(this.updater(val)).trigger('change'); this.$target.val(this.map[val]).trigger('change'); this.$source.val(this.map[val]).trigger('change'); this.$container.addClass('combobox-selected'); this.selected = true; return this.hide(); } , updater: function (item) { return item; } , show: function () { var pos = $.extend({}, this.$element.position(), { height: this.$element[0].offsetHeight }); this.$menu .insertAfter(this.$element) .css({ top: pos.top + pos.height , left: pos.left }) .show(); $('.dropdown-menu').on('mousedown', $.proxy(this.scrollSafety, this)); this.shown = true; return this; } , hide: function () { this.$menu.hide(); $('.dropdown-menu').off('mousedown', $.proxy(this.scrollSafety, this)); this.$element.on('blur', $.proxy(this.blur, this)); this.shown = false; return this; } , lookup: function (event) { this.query = this.$element.val(); return this.process(this.source); } , process: function (items) { var that = this; items = $.grep(items, function (item) { return that.matcher(item); }) items = this.sorter(items); if (!items.length) { return this.shown ? this.hide() : this; } return this.render(items.slice(0, this.options.items)).show(); } , template: function() { if (this.options.bsVersion == '2') { return '
' } else { return '
' } } , matcher: function (item) { return ~item.toLowerCase().indexOf(this.query.toLowerCase()); } , sorter: function (items) { var beginswith = [] , caseSensitive = [] , caseInsensitive = [] , item; while (item = items.shift()) { if (!item.toLowerCase().indexOf(this.query.toLowerCase())) {beginswith.push(item);} else if (~item.indexOf(this.query)) {caseSensitive.push(item);} else {caseInsensitive.push(item);} } return beginswith.concat(caseSensitive, caseInsensitive); } , highlighter: function (item) { var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&'); return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) { return '' + match + ''; }) } , render: function (items) { var that = this; items = $(items).map(function (i, item) { i = $(that.options.item).attr('data-value', item); i.find('a').html(that.highlighter(item)); return i[0]; }) items.first().addClass('active'); this.$menu.html(items); return this; } , next: function (event) { var active = this.$menu.find('.active').removeClass('active') , next = active.next(); if (!next.length) { next = $(this.$menu.find('li')[0]); } next.addClass('active'); } , prev: function (event) { var active = this.$menu.find('.active').removeClass('active') , prev = active.prev(); if (!prev.length) { prev = this.$menu.find('li').last(); } prev.addClass('active'); } , toggle: function () { if (!this.disabled) { if (this.$container.hasClass('combobox-selected')) { this.clearTarget(); this.triggerChange(); this.clearElement(); } else { if (this.shown) { this.hide(); } else { this.clearElement(); this.lookup(); } } } } , scrollSafety: function(e) { if (e.target.tagName == 'UL') { this.$element.off('blur'); } } , clearElement: function () { this.$element.val('').focus(); } , clearTarget: function () { this.$source.val(''); this.$target.val(''); this.$container.removeClass('combobox-selected'); this.selected = false; } , triggerChange: function () { this.$source.trigger('change'); } , refresh: function () { this.source = this.parse(); this.options.items = this.source.length; } , listen: function () { this.$element .on('focus', $.proxy(this.focus, this)) .on('blur', $.proxy(this.blur, this)) .on('keypress', $.proxy(this.keypress, this)) .on('keyup', $.proxy(this.keyup, this)); if (this.eventSupported('keydown')) { this.$element.on('keydown', $.proxy(this.keydown, this)); } this.$menu .on('click', $.proxy(this.click, this)) .on('mouseenter', 'li', $.proxy(this.mouseenter, this)) .on('mouseleave', 'li', $.proxy(this.mouseleave, this)); this.$button .on('click', $.proxy(this.toggle, this)); } , eventSupported: function(eventName) { var isSupported = eventName in this.$element; if (!isSupported) { this.$element.setAttribute(eventName, 'return;'); isSupported = typeof this.$element[eventName] === 'function'; } return isSupported; } , move: function (e) { if (!this.shown) {return;} switch(e.keyCode) { case 9: // tab case 13: // enter case 27: // escape e.preventDefault(); break; case 38: // up arrow e.preventDefault(); this.prev(); this.fixMenuScroll(); break; case 40: // down arrow e.preventDefault(); this.next(); this.fixMenuScroll(); break; } e.stopPropagation(); } , fixMenuScroll: function(){ var active = this.$menu.find('.active'); if(active.length){ var top = active.position().top; var bottom = top + active.height(); var scrollTop = this.$menu.scrollTop(); var menuHeight = this.$menu.height(); if(bottom > menuHeight){ this.$menu.scrollTop(scrollTop + bottom - menuHeight); } else if(top < 0){ this.$menu.scrollTop(scrollTop + top); } } } , keydown: function (e) { this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]); this.move(e); } , keypress: function (e) { if (this.suppressKeyPressRepeat) {return;} this.move(e); } , keyup: function (e) { switch(e.keyCode) { case 40: // down arrow if (!this.shown){ this.toggle(); } break; case 39: // right arrow case 38: // up arrow case 37: // left arrow case 36: // home case 35: // end case 16: // shift case 17: // ctrl case 18: // alt break; case 9: // tab case 13: // enter if (!this.shown) {return;} this.select(); break; case 27: // escape if (!this.shown) {return;} this.hide(); break; default: this.clearTarget(); this.lookup(); } e.stopPropagation(); e.preventDefault(); } , focus: function (e) { this.focused = true; } , blur: function (e) { var that = this; this.focused = false; var val = this.$element.val(); if (!this.selected && val !== '' ) { this.$element.val(''); this.$source.val('').trigger('change'); this.$target.val('').trigger('change'); } if (!this.mousedover && this.shown) {setTimeout(function () { that.hide(); }, 200);} } , click: function (e) { e.stopPropagation(); e.preventDefault(); this.select(); this.$element.focus(); } , mouseenter: function (e) { this.mousedover = true; this.$menu.find('.active').removeClass('active'); $(e.currentTarget).addClass('active'); } , mouseleave: function (e) { this.mousedover = false; } }; /* COMBOBOX PLUGIN DEFINITION * =========================== */ $.fn.combobox = function ( option ) { return this.each(function () { var $this = $(this) , data = $this.data('combobox') , options = typeof option == 'object' && option; if(!data) {$this.data('combobox', (data = new Combobox(this, options)));} if (typeof option == 'string') {data[option]();} }); }; $.fn.combobox.defaults = { bsVersion: '3' , menu: '' , item: '
  • ' }; $.fn.combobox.Constructor = Combobox; }( window.jQuery ); os-api-ref-1.4.0/os_api_ref/assets/api-site.js0000664000175000017500000001502313120043152022255 0ustar jenkinsjenkins00000000000000(function() { // the list of expanded element ids var expanded = []; // whether we should sync expand changes with the location // url. We need to make this false during large scale // operations because we're using the history API, which is // expensive. So a bulk expand turns this off, expands // everything, turns it back on, then does a history sync. var should_sync = true; $(document).ready(function() { // Change the text on the expando buttons when // appropriate. This also add or removes them to the list of // expanded sections, and then syncs that list to the history // after such a change. $('.api-detail') .on('hide.bs.collapse', function(e) { processButton(this, 'detail'); var index = expanded.indexOf(this.id); if (index > -1) { expanded.splice(index, 1); } sync_expanded(); }) .on('show.bs.collapse', function(e) { processButton(this, 'close'); expanded.push(this.id); sync_expanded(); }); // Expand the world. Wires up the expand all button, it turns // off the sync while it is running to save the costs with the // history API. var expandAllActive = true; $('#expand-all').click(function () { should_sync = false; if (expandAllActive) { expandAllActive = false; $('.api-detail').collapse('show'); $('#expand-all').attr('data-toggle', ''); $(this).text('Hide All'); } else { expandAllActive = true; $('.api-detail').collapse('hide'); $('#expand-all').attr('data-toggle', 'collapse'); $(this).text('Show All'); } should_sync = true; sync_expanded(); }); // if there is an expanded parameter passed in a url, we run // through and expand all the appropriate things. if (window.location.search.substring(1).indexOf("expanded") > -1) { should_sync = false; var parts = window.location.search.substring(1).split('&'); for (var i = 0; i < parts.length; i++) { var keyval = parts[i].split('='); if (keyval[0] == "expanded" && keyval[1]) { var expanded_ids = keyval[1].split(','); for (var j = 0; j < expanded_ids.length; j++) { $('#' + expanded_ids[j]).collapse('show'); } } } should_sync = true; // This is needed because the hash *might* be inside a // collapsed section. // // NOTE(sdague): this doesn't quite seem to work while // we're changing the rest of the document. $(document.body).scrollTop($(window.location.hash).offset().top); } // Wire up microversion selector $('.mv_selector').on('click', function(e) { var version = e.currentTarget.innerHTML; // flip what is active $(this).addClass('active').siblings().removeClass('active'); if (version == "All") { reset_microversion(); } else { set_microversion(version); } }); }); /** * Helper function for setting the text, styles for expandos */ function processButton(button, text) { $('#' + $(button).attr('id') + '-btn').text(text) .toggleClass('btn-info') .toggleClass('btn-default'); } // Take the expanded array and push it into history. Because // sphinx is building css appropriate ids, they should not have // any special characters we need to encode. So we can simply join // them into a comma separated list. function sync_expanded() { if (should_sync) { var url = UpdateQueryString('expanded', expanded.join(',')); history.pushState('', 'new expand', url); } } // Generically update the query string for a url. Credit to // http://stackoverflow.com/questions/5999118/add-or-update-query-string-parameter // for making this properly generic. function UpdateQueryString(key, value, url) { if (!url) url = window.location.href; var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"), hash; if (re.test(url)) { if (typeof value !== 'undefined' && value !== null) return url.replace(re, '$1' + key + "=" + value + '$2$3'); else { hash = url.split('#'); url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, ''); if (typeof hash[1] !== 'undefined' && hash[1] !== null) url += '#' + hash[1]; return url; } } else { if (typeof value !== 'undefined' && value !== null) { var separator = url.indexOf('?') !== -1 ? '&' : '?'; hash = url.split('#'); url = hash[0] + separator + key + '=' + value; if (typeof hash[1] !== 'undefined' && hash[1] !== null) url += '#' + hash[1]; return url; } else return url; } } // Set the Y value of the microversion to turn on / off visibility // of components. function set_microversion(number) { var major = number.split(".")[0]; var micro = number.split(".")[1]; for (var i = os_min_mv; i <= os_max_mv; i++) { var max_class = ".rp_max_ver_" + major + "_" + i; var min_class = ".rp_min_ver_" + major + "_" + i; if (i < micro) { $(max_class).hide(400); $(min_class).show(400); } else if (i >= micro) { $(min_class).hide(400); $(max_class).show(400); } } } function reset_microversion() { $('[class^=rp_min_ver]').show(400); $('[class^=rp_max_ver]').show(400); } $(document).ready(function(){ $('#mv_select').combobox({appendId: '-visable'}); $('#mv_select').on('change', function() { var version = this.value; if (version == "") { reset_microversion(); } else { set_microversion(version); } }); }); })(); os-api-ref-1.4.0/os_api_ref/assets/api-site.css0000664000175000017500000000772613120043152022444 0ustar jenkinsjenkins00000000000000tt.literal { padding: 2px 4px; font-size: 90%; color: #c7254e; white-space: nowrap; background-color: #f9f2f4; border-radius: 4px; } /* bootstrap users blockquote for pull quotes, so they are much larger, we need them smaller */ blockquote { font-size: 1em; } .docs-book-wrapper { width: 90% !important } tbody>tr:nth-child(odd)>td, tbody>tr:nth-child(odd)>th { background-color: #f9f9f9; } td>p { margin: 0 0 0.5em; } .operation-grp { padding-top: 0.5em; padding-bottom: 1em; } /* Ensure the method buttons and their links don't split lines when the page is narrower */ .operation { /* this moves the link icon into the gutter */ margin-left: -1.25em; margin-right: 1.25em; white-space: nowrap; } /* These make the links only show up on hover */ a.operation-anchor { visibility: hidden; } .operation-grp:hover a.operation-anchor { visibility: visible; } /* All parameter tables should be full width */ .api-detail table.docutils { width: 100%; } .versionmodified { font-weight: bold; } .label-POST { background-color: #5cb85c; } .label-POST[href]:hover, .label-POST[href]:focus { background-color: #449d44; } .label-GET, .label-HEAD { background-color: #5bc0de; } .label-GET[href]:hover, .label-GET[href]:focus, .label-HEAD[href]:hover, .label-HEAD[href]:focus { background-color: #31b0d5; } .label-PUT, .label-PATCH { background-color: #f0ad4e; } .label-PUT[href]:hover, .label-PUT[href]:focus, .label-PATCH[href]:hover, .label-PATCH[href]:focus { background-color: #ec971f; } .label-COPY { background-color: #6666ff; } .label-COPY[href]:hover, .label-COPY[href]:focus { background-color: #6699ff; } .label-DELETE { background-color: #d9534f; } .label-DELETE[href]:hover, .label-DELETE[href]:focus { background-color: #c9302c; } .btn-detail:hover, .btn-detail:focus, .btn-expand-all:hover, .btn-expand-all:focus { color: #fff; background-color: #3b6c91; border-color: #269abc; } .btn-detail, .btn-expand-all { color: #fff; background-color: #2A4E68; } span.path_parameter { font-family: monospace; padding: 2px 4px; font-size: 90%; color: #c7254e; white-space: nowrap; background-color: #f9f2f4; border-radius: 4px; } /* for microversion selector */ .mv_selector { font-size: 0.8em; padding: 0.3em; } .mv_selector.active { color: #fff; background-color: #31b0d5; border-color: #269abc; } p.url-subtitle { color: #555; font-weight: bold; } .docs-body .section h1 { display: block; } div.docs-sidebar-toc > div > ul > li { list-style-type: none; font-size: 0.8em; font-weight: bold; } div.docs-sidebar-toc > div > ul { padding-left: 20px } div.docs-sidebar-toc > div > ul > li > ul > li { list-style-type: disc; font-weight: normal; } div.docs-top-contents { display: none; } div.endpoint-container{ padding-left: 15px; } #expand-all { margin-top: 23px; } ### Combobox Experiment @media (min-width: 768px) { .form-search .combobox-container, .form-inline .combobox-container { display: inline-block; margin-bottom: 0; vertical-align: top; } .form-search .combobox-container .input-group-addon, .form-inline .combobox-container .input-group-addon { width: auto; } } .combobox-selected .caret { display: none; } /* :not doesn't work in IE8 */ .combobox-container:not(.combobox-selected) .glyphicon-remove { display: none; } .typeahead-long { max-height: 300px; overflow-y: auto; } .control-group.error .combobox-container .add-on { color: #B94A48; border-color: #B94A48; } .control-group.error .combobox-container .caret { border-top-color: #B94A48; } .control-group.warning .combobox-container .add-on { color: #C09853; border-color: #C09853; } .control-group.warning .combobox-container .caret { border-top-color: #C09853; } .control-group.success .combobox-container .add-on { color: #468847; border-color: #468847; } .control-group.success .combobox-container .caret { border-top-color: #468847; } os-api-ref-1.4.0/os_api_ref/http_codes.py0000664000175000017500000001744413120043153021422 0ustar jenkinsjenkins00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from docutils import nodes from docutils.parsers.rst.directives.tables import Table from docutils.statemachine import ViewList from six.moves.http_client import responses import yaml # cache for file -> yaml so we only do the load and check of a yaml # file once during a sphinx processing run. HTTP_YAML_CACHE = {} class HTTPResponseCodeDirective(Table): headers = ["Code", "Reason"] status_types = ("success", "error") # This is for HTTP response codes that OpenStack may use that are not part # the httplib response dict. CODES = { 429: "Too Many Requests", } required_arguments = 2 def __init__(self, *args, **kwargs): self.CODES.update(responses) super(HTTPResponseCodeDirective, self).__init__(*args, **kwargs) def _load_status_file(self, fpath): global HTTP_YAML_CACHE if fpath in HTTP_YAML_CACHE: return HTTP_YAML_CACHE[fpath] # self.app.info("Fpath: %s" % fpath) try: with open(fpath, 'r') as stream: lookup = yaml.safe_load(stream) except IOError: self.app.warn( "Parameters file %s not found" % fpath, (self.env.docname, None)) return except yaml.YAMLError as exc: self.app.warn(exc) raise HTTP_YAML_CACHE[fpath] = lookup return lookup def run(self): self.env = self.state.document.settings.env self.app = self.env.app # Make sure we have some content, which should be yaml that # defines some parameters. if not self.content: error = self.state_machine.reporter.error( 'No parameters defined', nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error] if not len(self.arguments) >= 2: error = self.state_machine.reporter.error( '%s' % self.arguments, nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error] _, status_defs_file = self.env.relfn2path(self.arguments.pop()) status_type = self.arguments.pop() self.status_defs = self._load_status_file(status_defs_file) # self.app.info("%s" % str(self.status_defs)) if status_type not in self.status_types: error = self.state_machine.reporter.error( 'Type %s is not one of %s' % (status_type, self.status_types), nodes.literal_block(self.block_text, self.block_text), line=self.lineno) return [error] self.yaml = self._load_codes() self.max_cols = len(self.headers) # TODO(sdague): it would be good to dynamically set column # widths (or basically make the colwidth thing go away # entirely) self.options['widths'] = [30, 70] self.col_widths = self.get_column_widths(self.max_cols) if isinstance(self.col_widths, tuple): # In docutils 0.13.1, get_column_widths returns a (widths, # colwidths) tuple, where widths is a string (i.e. 'auto'). # See https://sourceforge.net/p/docutils/patches/120/. self.col_widths = self.col_widths[1] # Actually convert the yaml title, messages = self.make_title() # self.app.info("Title %s, messages %s" % (title, messages)) table_node = self.build_table() self.add_name(table_node) title_block = nodes.title( text=status_type.capitalize()) section = nodes.section(ids=title_block) section += title_block section += table_node return [section] + messages def _load_codes(self): content = "\n".join(self.content) parsed = yaml.safe_load(content) new_content = list() for item in parsed: if isinstance(item, int): new_content.append((item, self.status_defs[item]['default'])) else: try: for code, reason in item.items(): new_content.append( (code, self.status_defs[code][reason]) ) except KeyError: self.app.warn( "Could not find %s for code %s" % (reason, code)) new_content.append( (code, self.status_defs[code]['default'])) return new_content def build_table(self): table = nodes.table() tgroup = nodes.tgroup(cols=len(self.headers)) table += tgroup # TODO(sdague): it would be really nice to figure out how not # to have this stanza, it kind of messes up all of the table # formatting because it doesn't let tables just be the right # size. tgroup.extend( nodes.colspec(colwidth=col_width, colname='c' + str(idx)) for idx, col_width in enumerate(self.col_widths) ) thead = nodes.thead() tgroup += thead row_node = nodes.row() thead += row_node row_node.extend(nodes.entry(h, nodes.paragraph(text=h)) for h in self.headers) tbody = nodes.tbody() tgroup += tbody rows, groups = self.collect_rows() tbody.extend(rows) table.extend(groups) return table def add_col(self, node): entry = nodes.entry() entry.append(node) return entry def add_desc_col(self, value): entry = nodes.entry() result = ViewList(value.split('\n')) self.state.nested_parse(result, 0, entry) return entry def collect_rows(self): rows = [] groups = [] try: # self.app.info("Parsed content is: %s" % self.yaml) for code, desc in self.yaml: h_code = http_code() h_code['code'] = code h_code['title'] = self.CODES.get(code, 'Unknown') trow = nodes.row() trow += self.add_col(h_code) trow += self.add_desc_col(desc) rows.append(trow) except AttributeError as exc: # if 'key' in locals(): self.app.warn("Failure on key: %s, values: %s. %s" % (code, desc, exc)) # else: # rows.append(self.show_no_yaml_error()) return rows, groups def http_code_html(self, node): tmpl = "%(code)s - %(title)s" self.body.append(tmpl % node) raise nodes.SkipNode class http_code(nodes.Part, nodes.Element): """Node for http_code stanza Because we need to insert very specific HTML at the final stage of processing, the http_code stanza needs a custom node type. This lets us accumulate the relevant data into this node, during parsing, but not turn it into known sphinx types (lists, tables, sections). Then, during the final build phase we transform directly to the html that we want. NOTE: this means we error trying to build latex or man pages for these stanza types right now. This is all fixable if we add an output formatter for this node type, but it's not yet a priority. Contributions welcomed. """ pass os-api-ref-1.4.0/PKG-INFO0000664000175000017500000001303413120043335015674 0ustar jenkinsjenkins00000000000000Metadata-Version: 1.1 Name: os-api-ref Version: 1.4.0 Summary: Sphinx Extensions to support API reference sites in OpenStack Home-page: http://docs.openstack.org/developer/os-api-ref Author: OpenStack Author-email: openstack-dev@lists.openstack.org License: UNKNOWN Description: ======================== Team and repository tags ======================== .. image:: http://governance.openstack.org/badges/os-api-ref.svg :target: http://governance.openstack.org/reference/tags/index.html .. Change things from this point on os-api-ref ========== Sphinx Extensions to support API reference sites in OpenStack This project is a collection of sphinx stanzas that assist in building an API Reference site for an OpenStack project in RST. RST is great for unstructured English, but displaying semi structured (and repetitive) data in tables is not its strength. This provides tooling to insert semi-structured data describing request and response parameters and status or error messages, and turn those into nice tables. The project also includes a set of styling (and javascript) that is expected to layer on top of a Sphinx theme base. This addition provides a nice set of collapsing sections for REST methods and javascript controls to expand / collapse all sections. Features -------- * Sphinx stanza ``rest_method`` describing the method and resource for a REST API call. Lets authors write simply and also gives readers a clean way to scan all methods then click a button to get more information about a method. * Sphinx stanza ``rest_parameters`` used to insert semi-structured data into the RST files describing the parameters users can send with the request. The stanza points to a structured YAML file, ``parameters.yaml``. * Sphinx stanza ``rest_status_code`` used to insert pointers to error or status codes returned by the service. Points to a structured YAML file, ``http_codes.yaml``. TODO ---- A list, in no particular order, of things we should do in this project. If you would like to contribute to any of these please show up in ``#openstack-dev`` on IRC and ask for ``sdague`` or ``mugsie`` to discuss or send an email to the openstack-dev@lists.openstack.org list with [api] in the subject line. * Enhance documentation with more examples and best practices * Testing for the code * ``max_microversion`` parameter support - so that we automatically tag parameters that have been removed * Make a microversion selector, so that you can get a version of the api-ref that hides all microversion elements beyond your selected version (this one is going to be a bit of complex javascript), in progress. Potential ideas ~~~~~~~~~~~~~~~ These aren't even quite todos, but just ideas about things that might be useful. * ``.. literalinclude`` is good for API samples files to be included, but should we have more markup that includes the full ``REST /URL`` as well. Sphinx stanzas -------------- **rest_method**: Enter the REST method, such as GET, PUT, POST, DELETE, followed by the resource (not including an endpoint) for the call. For example:: .. rest_method:: PUT /v2/images/{image_id}/file **rest_parameters**: Enter a reference to a ``parameters.yaml`` file and indicate which parameter you want to document. For example:: .. rest_parameters:: images-parameters.yaml - Content-type: Content-Type-data - image_id: image_id-in-path Where the ``images-parameters.yaml`` file contains pointers named ``Content-type`` and ``image_id`` and descriptions for each. **rest_status_code**: Enter a reference to a ``http-status.yaml`` file and indicate which errors or status codes you want to document. You can also add a pointer to more precise descriptions for each code. For example:: .. rest_status_code:: success http-codes.yaml - 204 .. rest_status_code:: error http-codes.yaml - 400: informal - 401 - 403 - 404 - 409 - 410: image-data-410 - 413: image-data-413 - 415: image-data-415 - 500: informal - 503: image-data-503 * Free software: Apache license * Documentation: http://docs.openstack.org/developer/os-api-ref * Source: http://git.openstack.org/cgit/openstack/os-api-ref Platform: UNKNOWN Classifier: Environment :: OpenStack Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX :: Linux Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 os-api-ref-1.4.0/CONTRIBUTING.rst0000664000175000017500000000122713120043152017236 0ustar jenkinsjenkins00000000000000If you would like to contribute to the development of OpenStack, you must follow the steps in this page: http://docs.openstack.org/infra/manual/developers.html If you already have a good understanding of how the system works and your OpenStack accounts are set up, you can skip to the development workflow section of this documentation to learn how changes to OpenStack should be submitted for review via the Gerrit tool: http://docs.openstack.org/infra/manual/developers.html#development-workflow Pull requests submitted through GitHub will be ignored. Bugs should be filed on Launchpad, not GitHub: https://bugs.launchpad.net/openstack-doc-tools os-api-ref-1.4.0/ChangeLog0000664000175000017500000000535613120043334016360 0ustar jenkinsjenkins00000000000000CHANGES ======= 1.4.0 ----- * Fix for sphinx 1.6.2 * Updated from global requirements * Updated from global requirements * Replaces yaml.load() with yaml.safe\_load() * Update tests for more recent sphinx * Enable warnings as errors * Updated from global requirements * [Fix gate]Update test requirement * Update hacking 1.3.0 ----- * Updated from global requirements * Delete support py33 * add file on releasing the software 1.2.0 ----- * Fix anchor link setting url bar * detail/close button, bug #1618955 * Removes unnecessary utf-8 encoding * Show team and repo badges on README * Updated from global requirements * Removes unnecessary utf-8 encoding * Add compatibility with docutils 0.13 * Add Constraints support * Import httplib from six to support Python 3 * Updated from global requirements * Add test for missing path params * microversion selector - dropdown 1.1.0 ----- * Sync with global-requirements * Update homepage with developer documentation page * Adds an example http-status.yaml file and updates doc * Use beautifulsoup4 instead of bs4 in test-requirements.txt * remove padding-top for endpoint-container * Adds more info to the README to instruct authors * Expand width of API Site 1.0.0 ----- * Update docs for openstackdocstheme * openstackdocstheme integration * Add color for COPY label * Change Layout of Path + Sub Title 0.4.0 ----- * Added docutils to requirements * Moved sphinx from test requirements to requirements * Tests for invalid parameter files * HTTP Response Code Table 0.3.0 ----- * add experimental microversion selector * track the expanded elements in the url * remove unused javascript code * Add warning for invalid parameters * Added more details to usage.rst * Highlight parameters in path * fix microversion parsing in parameters.yaml * add min/max version to rest method * simplify conf.py in tests * add a list of tests we should have * make testing be non parallel * tests for parameter out of order behavior * More unit tests * add first basic unit test * Trivial: fix typos in README.rst * Colour Code HTTP Methods * Validate in value before sorting validation * fix docs to link the new bug tracker 0.1.1 ----- * Make the version returned by the extension be the pbr version * Update css for version-added * Add parsing and output of max\_version * Remove errant ";" from the "expand\_all" detection 0.1.0 ----- * make unsorted parameters lists warnings * add section on warnings * document parameters.yaml and rest\_expand\_all * partial documentation on rest\_parameters * update usage for rest\_method * further enhance documentation * Update README * trim test-requirements.txt * Import the sphinx extension from nova * remove constraints, we're not going to use that * Initial Cookiecutter Commit * Added .gitreview os-api-ref-1.4.0/.coveragerc0000664000175000017500000000014513120043152016714 0ustar jenkinsjenkins00000000000000[run] branch = True source = os_api_ref omit = os_api_ref/openstack/* [report] ignore_errors = True os-api-ref-1.4.0/HACKING.rst0000664000175000017500000000024213120043152016367 0ustar jenkinsjenkins00000000000000os-api-ref Style Commandments =============================================== Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/ os-api-ref-1.4.0/RELEASING.rst0000664000175000017500000000227013120043152016637 0ustar jenkinsjenkins00000000000000=========== Releasing =========== This documents the how and when to release ``os-api-ref``. When to release =============== Any time there are fixes or additions ready to go, they should be released. Releases are cheap. If it's been more than a month and there are changes in master, consider releasing them. If the changes are entirely on the CSS / JS cosmetic side, things are usually pretty safe to release as long as they have been spot checked against a couple of projects. (The gate does the nova tree automatically). If new warnings are added ------------------------- If **new** warnings have been added since the last release, care should be taken to: * Alert the mailing list 2 days before the release about the new warning coming in (that should give them time to go non enforcing or fix the issue). * Ensure that you bump at least the Y in the version number (X.Y.Z). New warnings are not a Z level release. How to release ============== Check out ``openstack/releases`` Edit ``deliverables/_independent/os-api-ref.yaml`` Add a line with the version number desired, the git has of the commit that should be that release. If you have questions ask in ``#openstack-release`` os-api-ref-1.4.0/TESTS.rst0000664000175000017500000000052213120043152016226 0ustar jenkinsjenkins00000000000000============================== Tests that should be written ============================== Negative * test warning when groups are out of order * test when parameter keys are missing * test when description RST is invalid * test when parameter file is missing Microversion * test attributes are set when microversions are annotated. os-api-ref-1.4.0/tools/0000775000175000017500000000000013120043335015736 5ustar jenkinsjenkins00000000000000os-api-ref-1.4.0/tools/tox_install.sh0000775000175000017500000000203613120043152020633 0ustar jenkinsjenkins00000000000000#!/usr/bin/env bash # Client constraint file contains this client version pin that is in conflict # with installing the client from source. We should remove the version pin in # the constraints file before applying it for from-source installation. CONSTRAINTS_FILE="$1" shift 1 set -e # NOTE(tonyb): Place this in the tox enviroment's log dir so it will get # published to logs.openstack.org for easy debugging. localfile="$VIRTUAL_ENV/log/upper-constraints.txt" if [[ "$CONSTRAINTS_FILE" != http* ]]; then CONSTRAINTS_FILE="file://$CONSTRAINTS_FILE" fi # NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep curl "$CONSTRAINTS_FILE" --insecure --progress-bar --output "$localfile" pip install -c"$localfile" openstack-requirements # This is the main purpose of the script: Allow local installation of # the current repo. It is listed in constraints file and thus any # install will be constrained and we need to unconstrain it. edit-constraints "$localfile" -- "$CLIENT_NAME" pip install -c"$localfile" -U "$@" exit $? os-api-ref-1.4.0/requirements.txt0000664000175000017500000000053413120043152020061 0ustar jenkinsjenkins00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. pbr!=2.1.0,>=2.0.0 # Apache-2.0 PyYAML>=3.10.0 # MIT six>=1.9.0 # MIT sphinx!=1.6.1,>=1.5.1 # BSD openstackdocstheme>=1.5.0 # Apache-2.0 os-api-ref-1.4.0/setup.cfg0000664000175000017500000000225513120043335016423 0ustar jenkinsjenkins00000000000000[metadata] name = os-api-ref summary = Sphinx Extensions to support API reference sites in OpenStack description-file = README.rst author = OpenStack author-email = openstack-dev@lists.openstack.org home-page = http://docs.openstack.org/developer/os-api-ref classifier = Environment :: OpenStack Intended Audience :: Information Technology Intended Audience :: System Administrators License :: OSI Approved :: Apache Software License Operating System :: POSIX :: Linux Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 Programming Language :: Python :: 3.4 [files] packages = os_api_ref [build_sphinx] source-dir = doc/source build-dir = doc/build all_files = 1 warning-is-error = 1 [upload_sphinx] upload-dir = doc/build/html [compile_catalog] directory = os_api_ref/locale domain = os_api_ref [update_catalog] domain = os_api_ref output_dir = os_api_ref/locale input_file = os_api_ref/locale/os_api_ref.pot [extract_messages] keywords = _ gettext ngettext l_ lazy_gettext mapping_file = babel.cfg output_file = os_api_ref/locale/os_api_ref.pot [egg_info] tag_build = tag_date = 0