diff --git a/.travis.yml b/.travis.yml index c928a6a..e5aab2e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,30 @@ language: python -cache: pip - +sudo: false python: - - '3.4' - - '3.5' - - '3.6' + - '2.7' + - '3.4' + - '3.5' + - '3.6' -env: - - DRF=3.7 - - DRF=3.8 +cache: + directories: + - $HOME/.cache/pip + - .tox +before_cache: + - rm -f $HOME/.cache/pip/log/debug.log + - rm -fr .tox/log/ .tox/*/log/ .tox/*/tmp/ .tox/dist .tox/*/lib/*/site-packages/drf_yasg* jobs: include: - - stage: test - python: '2.7' - env: DRF=3.7 + - # workaround for python 3.7 on travis https://github.com/travis-ci/travis-ci/issues/9815#issuecomment-401756442 + stage: test + python: '3.7' + dist: xenial + sudo: required - python: '3.6' - env: DRF=master - - + env: TOXENV=djmaster + - # readthedocs uses python 3.5 for building python: '3.5' env: TOXENV=docs - @@ -40,29 +46,26 @@ jobs: allow_failures: - env: TOXENV=lint - - env: DRF=master + - env: TOXENV=djmaster fast_finish: true install: - - pip install -r requirements/ci.txt + - python -m pip install -U pip + - pip install -U -r requirements/ci.txt before_script: - coverage erase - - | - [[ -z "$TOXENV" && -z "$PYPI_DEPLOY" ]] && REPORT_COVERAGE="yes" || REPORT_COVERAGE="no"; - echo "Reporting coverage: ${REPORT_COVERAGE}" - - | - [[ -z "$TOXENV" && ! -z "$DRF" && "$DRF" != "master" ]] && USE_DETOX="yes" || USE_DETOX="no"; - echo "Using detox: ${USE_DETOX}" script: - - 'if [[ "$USE_DETOX" == "yes" ]]; then detox; else tox; fi' + - tox after_success: - - coverage combine - - 'if [[ "$REPORT_COVERAGE" == "yes" ]]; then coverage report; fi' - - 'if [[ "$REPORT_COVERAGE" == "yes" ]]; then codecov; fi' + - | + if [[ -z "$TOXENV" && -z "$PYPI_DEPLOY" ]]; then + chmod +x coverage.sh + ./coverage.sh + fi branches: only: diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 90e0bc2..d6c8181 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -35,8 +35,8 @@ You want to contribute some code? Great! Here are a few steps to get you started $ virtualenv venv $ source venv/bin/activate - (venv) $ pip install -e .[validation] - (venv) $ pip install -r requirements/dev.txt + (venv) $ pip install -U -e .[validation] + (venv) $ pip install -U -r requirements/dev.txt #. **Make your changes and check them against the test project** diff --git a/README.rst b/README.rst index e4b2213..f262ebc 100644 --- a/README.rst +++ b/README.rst @@ -11,9 +11,9 @@ Generate **real** Swagger/OpenAPI 2.0 specifications from a Django Rest Framewor Compatible with -- **Django Rest Framework**: 3.7.7, 3.8.x -- **Django**: 1.11.x, 2.0.x -- **Python**: 2.7, 3.4, 3.5, 3.6 +- **Django Rest Framework**: 3.7.7, 3.8 +- **Django**: 1.11, 2.0, 2.1 +- **Python**: 2.7, 3.4, 3.5, 3.6, 3.7 Resources: @@ -85,14 +85,14 @@ The preferred instalation method is directly from pypi: .. code:: console - pip install drf-yasg + pip install -U drf-yasg Additionally, if you want to use the built-in validation mechanisms (see `4. Validation`_), you need to install some extra requirements: .. code:: console - pip install drf-yasg[validation] + pip install -U drf-yasg[validation] .. _readme-quickstart: @@ -294,7 +294,7 @@ For additional usage examples, you can take a look at the test project in the `` $ virtualenv venv $ source venv/bin/activate (venv) $ cd testproj - (venv) $ pip install -r requirements.txt + (venv) $ pip install -U -r requirements.txt (venv) $ python manage.py migrate (venv) $ python manage.py shell -c "import createsuperuser" (venv) $ python manage.py runserver @@ -315,8 +315,8 @@ From here on, the terms “OpenAPI” and “Swagger” are used interchangeably Swagger in Django Rest Framework ================================ -Since Django Rest 3.7, there is now `built in support `__ for -automatic OpenAPI 2.0 schema generation. However, this generation is based on the `coreapi `__ +Since Django Rest Framework 3.7, there is now `built in support `__ +for automatic OpenAPI 2.0 schema generation. However, this generation is based on the `coreapi `__ standard, which for the moment is vastly inferior to OpenAPI in both features and tooling support. In particular, the OpenAPI codec/compatibility layer provided has a few major problems: @@ -329,18 +329,15 @@ In short this makes the generated schema unusable for code generation, and medio Other libraries =============== -There are currently two decent Swagger schema generators that I could -find for django-rest-framework: +There are currently two decent Swagger schema generators that I could find for django-rest-framework: * `django-rest-swagger `__ * `drf-openapi `__ -Out of the two, ``django-rest-swagger`` is just a wrapper around DRF 3.7 schema generation with an added UI, and -thus presents the same problems. ``drf-openapi`` is a bit more involved and implements some custom handling for response -schemas, but ultimately still falls short in code generation because the responses are plain of lacking support for -named schemas. - -Both projects are also currently unmantained. +``django-rest-swagger`` is just a wrapper around DRF 3.7 schema generation with an added UI, and +thus presents the same problems, while also being unmaintained. ``drf-openapi`` was +`discontinued by the author `_ +on April 3rd, 2018. ************************ Third-party integrations diff --git a/coverage.sh b/coverage.sh new file mode 100755 index 0000000..3e4a51e --- /dev/null +++ b/coverage.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -ex + +coverage combine +coverage report +codecov diff --git a/requirements.txt b/requirements.txt index 5a5a649..b7d456c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ +-r requirements/setup.txt .[validation] -r requirements/heroku.txt diff --git a/requirements/dev.txt b/requirements/dev.txt index 8a866e0..9e61e77 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,6 +1,4 @@ -# requirements for local development to be installed via pip install -r requirements/dev.txt +# requirements for local development to be installed via pip install -U -r requirements/dev.txt -r tox.txt -r test.txt -r lint.txt - -tox-battery>=0.5 diff --git a/requirements/docs.txt b/requirements/docs.txt index 58790aa..b528a74 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -4,5 +4,5 @@ sphinx_rtd_theme>=0.2.4 Pillow>=4.3.0 readme_renderer>=17.2 -Django>=2.0,<2.1 +Django>=2.0 djangorestframework_camel_case>=0.2.0 diff --git a/requirements/setup.txt b/requirements/setup.txt index 72e1362..bf6789e 100644 --- a/requirements/setup.txt +++ b/requirements/setup.txt @@ -1,4 +1,3 @@ # needed to build the package setup_requires in setup.py -# do not unpin this (see setup.py) -setuptools_scm==1.15.6 +setuptools-scm>=3.0.6 diff --git a/requirements/test.txt b/requirements/test.txt index 66cbe9c..135152b 100644 --- a/requirements/test.txt +++ b/requirements/test.txt @@ -1,5 +1,5 @@ # requirements for running the tests via pytest -pytest>=2.9 +pytest>=2.9,<3.7 # <3.7 because of incompatible pluggy requirement pytest-pythonpath>=0.7.1 pytest-cov>=2.5.1 pytest-xdist>=1.22.0 diff --git a/requirements/tox.txt b/requirements/tox.txt index 722c32b..6e3809e 100644 --- a/requirements/tox.txt +++ b/requirements/tox.txt @@ -1,5 +1,5 @@ # requirements for building and running tox -tox>=2.9.1,<3.0.0 -detox>=0.11 +tox>=3.1.2 +tox-battery>=0.5 -r setup.txt diff --git a/setup.py b/setup.py old mode 100644 new mode 100755 index f462f5b..08d17ef --- a/setup.py +++ b/setup.py @@ -1,10 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -import distutils.core import io import os -import random -import string import sys from setuptools import find_packages, setup @@ -22,50 +19,24 @@ requirements_setup = read_req('setup.txt') requirements_validation = read_req('validation.txt') -def _install_setup_requires(attrs): - # copied from setuptools - dist = distutils.core.Distribution(dict( - (k, v) for k, v in attrs.items() - if k in ('dependency_links', 'setup_requires') - )) - # Honor setup.cfg's options. - dist.parse_config_files(ignore_option_errors=True) - if dist.setup_requires: - dist.fetch_build_eggs(dist.setup_requires) - - -try: - # try to install setuptools_scm before setuptools does it, otherwise our monkey patch below will come too early - # (setuptools_scm adds find_files hooks into setuptools on install) - _install_setup_requires({'setup_requires': requirements_setup}) -except Exception: - pass - -if 'sdist' in sys.argv: - try: - # see https://github.com/pypa/setuptools_scm/issues/190, setuptools_scm includes ALL versioned files from - # the git repo into the sdist by default, and there is no easy way to provide an opt-out; - # this hack is ugly but does the job; because this is not really a documented interface of the module, - # the setuptools_scm version should remain pinned to ensure it keeps working - import setuptools_scm.integration - - setuptools_scm.integration.find_files = lambda _: [] - except ImportError: - pass - try: # this is a workaround for being able to install the package from source without working from a git checkout # it is needed for building succesfully on Heroku from setuptools_scm import get_version +except ImportError: + get_version = None +try: version = get_version() version_kwargs = {'use_scm_version': True} -except LookupError: - if 'sdist' in sys.argv or 'bdist_wheel' in sys.argv: +except Exception: + if any(any(dist in arg for dist in ['sdist', 'bdist']) for arg in sys.argv): raise - rnd = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(16)) - version_kwargs = {'version': '0.0.0.dummy+' + rnd} + import time + timestamp_ms = int(time.time() * 1000) + timestamp_str = hex(timestamp_ms)[2:].zfill(16) + version_kwargs = {'version': '0.0.0.dummy+' + timestamp_str} setup( name='drf-yasg', @@ -89,7 +60,7 @@ setup( classifiers=[ 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', - 'Development Status :: 4 - Beta', + 'Development Status :: 5 - Production/Stable', 'Operating System :: OS Independent', 'Environment :: Web Environment', 'Programming Language :: Python', @@ -99,9 +70,11 @@ setup( 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', 'Framework :: Django', 'Framework :: Django :: 1.11', 'Framework :: Django :: 2.0', + 'Framework :: Django :: 2.1', 'Topic :: Documentation', 'Topic :: Software Development :: Code Generators', ], diff --git a/src/drf_yasg/codecs.py b/src/drf_yasg/codecs.py index 9739f75..c150d50 100644 --- a/src/drf_yasg/codecs.py +++ b/src/drf_yasg/codecs.py @@ -5,7 +5,6 @@ import json from collections import OrderedDict from coreapi.compat import force_bytes -from django.utils.safestring import SafeData, SafeText from ruamel import yaml from . import openapi diff --git a/src/drf_yasg/utils.py b/src/drf_yasg/utils.py index 67a1ac6..72a0d46 100644 --- a/src/drf_yasg/utils.py +++ b/src/drf_yasg/utils.py @@ -117,7 +117,7 @@ def swagger_auto_schema(method=None, methods=None, auto_schema=unset, request_bo # no overrides to set, no use in doing more work return - # if the method is an @action, it will have a bind_to_methods attribute + # if the method is an @action, it will have a bind_to_methods attribute, or a mapper attribute for drf>3.8 bind_to_methods = getattr(view_method, 'bind_to_methods', []) # if the method is actually a function based view (@api_view), it will have a 'cls' attribute view_cls = getattr(view_method, 'cls', None) diff --git a/testproj/manage.py b/testproj/manage.py old mode 100644 new mode 100755 diff --git a/tests/test_management.py b/tests/test_management.py index c3cdd40..0ce1c55 100644 --- a/tests/test_management.py +++ b/tests/test_management.py @@ -1,5 +1,3 @@ -from six import StringIO - import json import os import random diff --git a/tox.ini b/tox.ini index 9ce7fef..3789fd0 100644 --- a/tox.ini +++ b/tox.ini @@ -1,28 +1,29 @@ [tox] +# https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django envlist = - py27-django111-drf37, - py{34,35,36}-django{111,20}-drf{37,38}, - py36-django20-drfmaster, - lint, docs - -[travis:env] -DRF = - 3.7: drf37 - 3.8: drf38 - master: drfmaster + py{27,34,35,36}-django111-drf37, + py{27,34,35,36}-django111-drf38, + py{34,35,36,37}-django20-drf37, + py{34,35,36,37}-django20-drf38, + py{35,36,37}-django21-drf37, + py{35,36,37}-django21-drf38, + djmaster, lint, docs [testenv] deps = django111: Django>=1.11,<2.0 django20: Django>=2.0,<2.1 + django21: Django>=2.1,<2.2 drf37: djangorestframework>=3.7.7,<3.8 drf38: djangorestframework>=3.8.0,<3.9 # test with the latest build of django-rest-framework to get early warning of compatibility issues - drfmaster: https://github.com/encode/django-rest-framework/archive/master.tar.gz + djmaster: https://github.com/encode/django-rest-framework/archive/master.tar.gz + djmaster: https://github.com/django/django/archive/master.tar.gz # other dependencies + -rrequirements/setup.txt -rrequirements/validation.txt -rrequirements/test.txt @@ -46,7 +47,7 @@ commands = [pytest] DJANGO_SETTINGS_MODULE = testproj.settings.local python_paths = testproj -addopts = -n 3 --ignore=node_modules +addopts = -n 2 --ignore=node_modules [flake8] max-line-length = 120 diff --git a/update-ui.sh b/update-ui.sh old mode 100644 new mode 100755