Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] add 'generate_swagger' management command #31

Merged
merged 15 commits into from
Dec 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ exclude_lines =

# Don't complain if tests don't hit defensive assertion code:
raise AssertionError
raise ImproperlyConfigured
raise TypeError
raise NotImplementedError
warnings.warn
Expand Down
36 changes: 22 additions & 14 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ Pull requests

You want to contribute some code? Great! Here are a few steps to get you started:

#. Fork the repository on GitHub
#. Clone your fork and create a branch for the code you want to add
#. Create a new virtualenv and install the package in development mode
#. **Fork the repository on GitHub**
#. **Clone your fork and create a branch for the code you want to add**
#. **Create a new virtualenv and install the package in development mode**

.. code:: console

Expand All @@ -38,25 +38,32 @@ You want to contribute some code? Great! Here are a few steps to get you started
(venv) $ pip install -e .[validation]
(venv) $ pip install -rrequirements/dev.txt -rrequirements/test.txt

#. Make your changes and check them against the test project
#. **Make your changes and check them against the test project**

.. code:: console

(venv) $ cd testproj
(venv) $ python manage.py migrate
(venv) $ cat createsuperuser.py | python manage.py shell
(venv) $ python manage.py runserver
(venv) $ curl localhost:8000/swagger.yaml
(venv) $ firefox localhost:8000/swagger/

#. Update the tests if necessary
#. **Update the tests if necessary**

You can find them in the ``tests`` directory.

If your change modifies the expected schema output, you should download the new generated ``swagger.yaml``, diff it
against the old reference output in ``tests/reference.yaml``, and replace it after checking that no unexpected
changes appeared.
If your change modifies the expected schema output, you should regenerate the reference schema at
``tests/reference.yaml``:

#. Run tests. The project is setup to use tox and pytest for testing
.. code:: console

(venv) $ cd testproj
(venv) $ python manage.py generate_swagger ../tests/reference.yaml --overwrite --user admin --url http://test.local:8002/

After checking the git diff to verify that no unexpected changes appeared, you should commit the new
``reference.yaml`` together with your changes.

#. **Run tests. The project is setup to use tox and pytest for testing**

.. code:: console

Expand All @@ -65,7 +72,7 @@ You want to contribute some code? Great! Here are a few steps to get you started
# (optional) run tests for other python versions in separate environments
(venv) $ tox

#. Update documentation
#. **Update documentation**

If the change modifies behaviour or adds new features, you should update the documentation and ``README.rst``
accordingly. Documentation is written in reStructuredText and built using Sphinx. You can find the sources in the
Expand All @@ -77,10 +84,11 @@ You want to contribute some code? Great! Here are a few steps to get you started

(venv) $ tox -e docs

#. Push your branch and submit a pull request to the master branch on GitHub
#. **Push your branch and submit a pull request to the master branch on GitHub**

Incomplete/Work In Progress pull requests are encouraged, because they allow you to get feedback and help more
easily.

#. Your code must pass all the required travis jobs before it is merged. As of now, this includes running on
Python 2.7, 3.4, 3.5 and 3.6, and building the docs succesfully.
#. **Your code must pass all the required travis jobs before it is merged**

As of now, this consists of running on Python 2.7, 3.4, 3.5 and 3.6, and building the docs succesfully.
111 changes: 58 additions & 53 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -180,62 +180,67 @@ The possible settings and their default values are as follows:

.. code:: python

SWAGGER_SETTINGS = {
# default inspector classes, see advanced documentation
'DEFAULT_AUTO_SCHEMA_CLASS': 'drf_yasg.inspectors.SwaggerAutoSchema',
'DEFAULT_FIELD_INSPECTORS': [
'drf_yasg.inspectors.CamelCaseJSONFilter',
'drf_yasg.inspectors.ReferencingSerializerInspector',
'drf_yasg.inspectors.RelatedFieldInspector',
'drf_yasg.inspectors.ChoiceFieldInspector',
'drf_yasg.inspectors.FileFieldInspector',
'drf_yasg.inspectors.DictFieldInspector',
'drf_yasg.inspectors.SimpleFieldInspector',
'drf_yasg.inspectors.StringDefaultFieldInspector',
],
'DEFAULT_FILTER_INSPECTORS': [
'drf_yasg.inspectors.CoreAPICompatInspector',
],
'DEFAULT_PAGINATOR_INSPECTORS': [
'drf_yasg.inspectors.DjangoRestResponsePagination',
'drf_yasg.inspectors.CoreAPICompatInspector',
],

'USE_SESSION_AUTH': True, # add Django Login and Django Logout buttons, CSRF token to swagger UI page
'LOGIN_URL': getattr(django.conf.settings, 'LOGIN_URL', None), # URL for the login button
'LOGOUT_URL': getattr(django.conf.settings, 'LOGOUT_URL', None), # URL for the logout button

# Swagger security definitions to include in the schema;
# see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object
'SECURITY_DEFINITIONS': {
'basic': {
'type': 'basic'
}
},

# url to an external Swagger validation service; defaults to 'http://online.swagger.io/validator/'
# set to None to disable the schema validation badge in the UI
'VALIDATOR_URL': '',

# swagger-ui configuration settings, see https://github.com/swagger-api/swagger-ui/blob/112bca906553a937ac67adc2e500bdeed96d067b/docs/usage/configuration.md#parameters
'OPERATIONS_SORTER': None,
'TAGS_SORTER': None,
'DOC_EXPANSION': 'list',
'DEEP_LINKING': False,
'SHOW_EXTENSIONS': True,
'DEFAULT_MODEL_RENDERING': 'model',
'DEFAULT_MODEL_DEPTH': 3,
}
SWAGGER_SETTINGS = {
# default inspector classes, see advanced documentation
'DEFAULT_AUTO_SCHEMA_CLASS': 'drf_yasg.inspectors.SwaggerAutoSchema',
'DEFAULT_FIELD_INSPECTORS': [
'drf_yasg.inspectors.CamelCaseJSONFilter',
'drf_yasg.inspectors.ReferencingSerializerInspector',
'drf_yasg.inspectors.RelatedFieldInspector',
'drf_yasg.inspectors.ChoiceFieldInspector',
'drf_yasg.inspectors.FileFieldInspector',
'drf_yasg.inspectors.DictFieldInspector',
'drf_yasg.inspectors.SimpleFieldInspector',
'drf_yasg.inspectors.StringDefaultFieldInspector',
],
'DEFAULT_FILTER_INSPECTORS': [
'drf_yasg.inspectors.CoreAPICompatInspector',
],
'DEFAULT_PAGINATOR_INSPECTORS': [
'drf_yasg.inspectors.DjangoRestResponsePagination',
'drf_yasg.inspectors.CoreAPICompatInspector',
],

# default api Info if none is otherwise given; should be an import string to an openapi.Info object
'DEFAULT_INFO': None,
# default API url if none is otherwise given
'DEFAULT_API_URL': '',

'USE_SESSION_AUTH': True, # add Django Login and Django Logout buttons, CSRF token to swagger UI page
'LOGIN_URL': getattr(django.conf.settings, 'LOGIN_URL', None), # URL for the login button
'LOGOUT_URL': getattr(django.conf.settings, 'LOGOUT_URL', None), # URL for the logout button

# Swagger security definitions to include in the schema;
# see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object
'SECURITY_DEFINITIONS': {
'basic': {
'type': 'basic'
}
},

# url to an external Swagger validation service; defaults to 'http://online.swagger.io/validator/'
# set to None to disable the schema validation badge in the UI
'VALIDATOR_URL': '',

# swagger-ui configuration settings, see https://github.com/swagger-api/swagger-ui/blob/112bca906553a937ac67adc2e500bdeed96d067b/docs/usage/configuration.md#parameters
'OPERATIONS_SORTER': None,
'TAGS_SORTER': None,
'DOC_EXPANSION': 'list',
'DEEP_LINKING': False,
'SHOW_EXTENSIONS': True,
'DEFAULT_MODEL_RENDERING': 'model',
'DEFAULT_MODEL_DEPTH': 3,
}

.. code:: python

REDOC_SETTINGS = {
# ReDoc UI configuration settings, see https://github.com/Rebilly/ReDoc#redoc-tag-attributes
'LAZY_RENDERING': True,
'HIDE_HOSTNAME': False,
'EXPAND_RESPONSES': 'all',
'PATH_IN_MIDDLE': False,
}
REDOC_SETTINGS = {
# ReDoc UI configuration settings, see https://github.com/Rebilly/ReDoc#redoc-tag-attributes
'LAZY_RENDERING': True,
'HIDE_HOSTNAME': False,
'EXPAND_RESPONSES': 'all',
'PATH_IN_MIDDLE': False,
}

3. Caching
==========
Expand Down
7 changes: 7 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ Changelog
#########


*********
**1.1.1**
*********

- **ADDED:** :ref:`generate_swagger management command <management-command>`
(:issue:`29`, :pr:`31`, thanks to :ghuser:`beaugunderson`)

*********
**1.1.0**
*********
Expand Down
20 changes: 10 additions & 10 deletions docs/custom_spec.rst
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ The ``@swagger_auto_schema`` decorator
You can use the :func:`@swagger_auto_schema <.swagger_auto_schema>` decorator on view functions to override
some properties of the generated :class:`.Operation`. For example, in a ``ViewSet``,

.. code:: python
.. code-block:: python

@swagger_auto_schema(operation_description="partial_update description override", responses={404: 'slug not found'})
def partial_update(self, request, *args, **kwargs):
Expand All @@ -153,7 +153,7 @@ Where you can use the :func:`@swagger_auto_schema <.swagger_auto_schema>` decora
* for function based ``@api_view``\ s, because the same view can handle multiple methods, and thus represent multiple
operations, you have to add the decorator multiple times if you want to override different operations:

.. code:: python
.. code-block:: python

test_param = openapi.Parameter('test', openapi.IN_QUERY, description="test manual param", type=openapi.TYPE_BOOLEAN)
user_response = openapi.Response('response description', UserSerializer)
Expand All @@ -169,7 +169,7 @@ Where you can use the :func:`@swagger_auto_schema <.swagger_auto_schema>` decora
* for class based ``APIView``, ``GenericAPIView`` and non-``ViewSet`` derivatives, you have to decorate the respective
method of each operation:

.. code:: python
.. code-block:: python

class UserList(APIView):
@swagger_auto_schema(responses={200: UserSerializer(many=True)})
Expand All @@ -186,7 +186,7 @@ Where you can use the :func:`@swagger_auto_schema <.swagger_auto_schema>` decora
respond to multiple HTTP methods and thus have multiple operations that must be decorated separately:


.. code:: python
.. code-block:: python

class ArticleViewSet(viewsets.ModelViewSet):
# method or 'methods' can be skipped because the list_route only handles a single method (GET)
Expand Down Expand Up @@ -214,7 +214,7 @@ Where you can use the :func:`@swagger_auto_schema <.swagger_auto_schema>` decora
If you want to customize the generation of a method you are not implementing yourself, you can use
``swagger_auto_schema`` in combination with Django's ``method_decorator``:

.. code:: python
.. code-block:: python

@method_decorator(name='list', decorator=swagger_auto_schema(
operation_description="description from swagger_auto_schema via method_decorator"
Expand All @@ -229,7 +229,7 @@ Where you can use the :func:`@swagger_auto_schema <.swagger_auto_schema>` decora
You can go even further and directly decorate the result of ``as_view``, in the same manner you would
override an ``@api_view`` as described above:

.. code:: python
.. code-block:: python

decorated_login_view = \
swagger_auto_schema(
Expand All @@ -256,7 +256,7 @@ Serializer ``Meta`` nested class

You can define some per-serializer options by adding a ``Meta`` class to your serializer, e.g.:

.. code:: python
.. code-block:: python

class WhateverSerializer(Serializer):
...
Expand Down Expand Up @@ -288,7 +288,7 @@ class-level attribute named ``swagger_schema`` on the view class, or

For example, to generate all operation IDs as camel case, you could do:

.. code:: python
.. code-block:: python

from inflection import camelize

Expand Down Expand Up @@ -331,7 +331,7 @@ For customizing behavior related to specific field, serializer, filter or pagina
A :class:`~.inspectors.FilterInspector` that adds a description to all ``DjangoFilterBackend`` parameters could be
implemented like so:

.. code:: python
.. code-block:: python

class DjangoFilterDescriptionInspector(CoreAPICompatInspector):
def get_filter_parameters(self, filter_backend):
Expand All @@ -357,7 +357,7 @@ implemented like so:
A second example, of a :class:`~.inspectors.FieldInspector` that removes the ``title`` attribute from all generated
:class:`.Schema` objects:

.. code:: python
.. code-block:: python

class NoSchemaTitleInspector(FieldInspector):
def process_result(self, result, method_name, obj, **kwargs):
Expand Down
27 changes: 26 additions & 1 deletion docs/rendering.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Serving the schema
##################


************************************************
``get_schema_view`` and the ``SchemaView`` class
************************************************
Expand All @@ -14,7 +15,7 @@ in the README for a usage example.

You can also subclass :class:`.SchemaView` by extending the return value of :func:`.get_schema_view`, e.g.:

.. code:: python
.. code-block:: python

SchemaView = get_schema_view(info, ...)

Expand All @@ -33,3 +34,27 @@ codec and the view.

You can use your custom renderer classes as kwargs to :meth:`.SchemaView.as_cached_view` or by subclassing
:class:`.SchemaView`.

.. _management-command:

******************
Management command
******************

.. versionadded:: 1.1.1

If you only need a swagger spec file in YAML or JSON format, you can use the ``generate_swagger`` management command
to get it without having to start the web server:

.. code-block:: console

$ python manage.py generate_swagger swagger.json

See the command help for more advanced options:

.. code-block:: console

$ python manage.py generate_swagger --help
usage: manage.py generate_swagger [-h] [--version] [-v {0,1,2,3}]
... more options ...

23 changes: 21 additions & 2 deletions docs/settings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Example:

**settings.py**

.. code:: python
.. code-block:: python

SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
Expand Down Expand Up @@ -91,6 +91,25 @@ Paginator inspectors given to :func:`@swagger_auto_schema <.swagger_auto_schema>
:class:`'drf_yasg.inspectors.CoreAPICompatInspector' <.inspectors.CoreAPICompatInspector>`, |br| \
``]``

Swagger document attributes
===========================

DEFAULT_INFO
------------

An import string to an :class:`.openapi.Info` object. This will be used when running the ``generate_swagger``
management command, or if no ``info`` argument is passed to ``get_schema_view``.

**Default**: :python:`None`

DEFAULT_API_URL
---------------

A string representing the default API URL. This will be used to populate the ``host``, ``schemes`` and ``basePath``
attributes of the Swagger document if no API URL is otherwise provided.

**Default**: :python:`''`

Authorization
=============

Expand Down Expand Up @@ -124,7 +143,7 @@ See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#sec

**Default**:

.. code:: python
.. code-block:: python

'basic': {
'type': 'basic'
Expand Down
Loading