Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| eed8a8d3ec | |||
| d04f27f40f | |||
| db154d196a | |||
| 60e1346150 | |||
| 69b628a7af | |||
| 64d9d42aa9 | |||
| e9d5344de3 | |||
| b5aba7243d | |||
| 91ef83e830 | |||
| 0991c806c7 | |||
| 59e86ff72f | |||
| 548489a539 | |||
| 887b53300a | |||
| f692fe7c98 | |||
| 017ae3d240 | |||
| b57413023b | |||
| 4014c69689 | |||
| 7bb4700003 | |||
| 86c1675c58 | |||
| 81f0b1a2ea | |||
| 298a9745df |
@@ -3,6 +3,7 @@ testproj/db.sqlite3
|
||||
testproj/staticfiles
|
||||
\.pytest_cache/
|
||||
docs/\.doctrees/
|
||||
pip-wheel-metadata/
|
||||
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Python template
|
||||
|
||||
Generated
+2
-1
@@ -19,6 +19,7 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/.cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.eggs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.pytest_cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.tox" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/dist" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/docs/.doctrees" />
|
||||
@@ -44,4 +45,4 @@
|
||||
<option name="projectConfiguration" value="pytest" />
|
||||
<option name="PROJECT_TEST_RUNNER" value="pytest" />
|
||||
</component>
|
||||
</module>
|
||||
</module>
|
||||
@@ -1,7 +1,6 @@
|
||||
language: python
|
||||
python:
|
||||
- '2.7'
|
||||
- '3.4'
|
||||
- '3.5'
|
||||
- '3.6'
|
||||
- '3.7'
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ You want to contribute some code? Great! Here are a few steps to get you started
|
||||
|
||||
#. **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.
|
||||
As of now, this consists of running on Python 2.7, 3.5, 3.6 and 3.7, and building the docs succesfully.
|
||||
|
||||
******************
|
||||
Maintainer's notes
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ Generate **real** Swagger/OpenAPI 2.0 specifications from a Django Rest Framewor
|
||||
Compatible with
|
||||
|
||||
- **Django Rest Framework**: 3.7.7, 3.8, 3.9
|
||||
- **Django**: 1.11, 2.0, 2.1
|
||||
- **Python**: 2.7, 3.4, 3.5, 3.6, 3.7
|
||||
- **Django**: 1.11, 2.0, 2.1, 2.2
|
||||
- **Python**: 2.7, 3.5, 3.6, 3.7
|
||||
|
||||
Only the latest patch version of each ``major.minor`` series of Python, Django and Django REST Framework is supported.
|
||||
|
||||
|
||||
@@ -2,6 +2,32 @@
|
||||
Changelog
|
||||
#########
|
||||
|
||||
**********
|
||||
**1.15.1**
|
||||
**********
|
||||
|
||||
*Release date: Jun 13, 2019*
|
||||
|
||||
- **IMPROVED:** updated ``swagger-ui`` to version 3.22.3
|
||||
- **IMPROVED:** updated ``ReDoc`` to version 2.0.0-rc.8-1
|
||||
- **FIXED:** fixed an issue with inspection of typing hints on Python 2.7 (:issue:`363`)
|
||||
- **FIXED:** fixed an issue with inspection of typing hints on Python 3.7 (:issue:`371`)
|
||||
|
||||
**Python 3.4 support has been dropped!**
|
||||
|
||||
|
||||
**********
|
||||
**1.15.0**
|
||||
**********
|
||||
|
||||
*Release date: Apr 01, 2019*
|
||||
|
||||
- **ADDED:** added ``is_list_view`` and ``has_list_response`` extension points to ``SwaggerAutoSchema`` (:issue:`331`)
|
||||
- **IMPROVED:** updated ``swagger-ui`` to version 3.22.0
|
||||
- **IMPROVED:** updated ``ReDoc`` to version 2.0.0-rc.4
|
||||
- **FIXED:** ``ListModelMixin`` will now always be treated as a list view (:issue:`306`)
|
||||
- **FIXED:** non-primtive values in field ``choices`` will now be handled properly (:issue:`340`)
|
||||
|
||||
**********
|
||||
**1.14.0**
|
||||
**********
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ This library generates OpenAPI 2.0 documents. The authoritative specification fo
|
||||
be the official documentation over at `swagger.io <https://swagger.io/>`__ and the `OpenAPI 2.0 specification
|
||||
page <https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md>`__.
|
||||
|
||||
Beause the above specifications are a bit heavy and convoluted, here is a general overview of how the specification
|
||||
Because the above specifications are a bit heavy and convoluted, here is a general overview of how the specification
|
||||
is structured, starting from the root ``Swagger`` object.
|
||||
|
||||
* :class:`.Swagger` object
|
||||
|
||||
+2
-2
@@ -340,7 +340,7 @@ values for Parameters.
|
||||
OAUTH2_REDIRECT_URL
|
||||
-------------------
|
||||
|
||||
Used when OAuth2 authenitcation of API requests via swagger-ui is desired. If ``None`` is passed, the
|
||||
Used when OAuth2 authentication of API requests via swagger-ui is desired. If ``None`` is passed, the
|
||||
``oauth2RedirectUrl`` parameter will be set to ``{% static 'drf-yasg/swagger-ui-dist/oauth2-redirect.html' %}``. This
|
||||
is the default `https://github.com/swagger-api/swagger-ui/blob/master/dist/oauth2-redirect.html <oauth2-redirect>`_
|
||||
file provided by ``swagger-ui``.
|
||||
@@ -351,7 +351,7 @@ file provided by ``swagger-ui``.
|
||||
OAUTH2_CONFIG
|
||||
-------------
|
||||
|
||||
Used when OAuth2 authenitcation of API requests via swagger-ui is desired. Provides OAuth2 configuration parameters
|
||||
Used when OAuth2 authentication of API requests via swagger-ui is desired. Provides OAuth2 configuration parameters
|
||||
to the ``SwaggerUIBundle#initOAuth`` method, and must be a dictionary. See
|
||||
`OAuth2 configuration <https://github.com/swagger-api/swagger-ui/blob/master/docs/usage/oauth2.md>`_.
|
||||
|
||||
|
||||
Generated
+844
-132
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "drf-yasg",
|
||||
"dependencies": {
|
||||
"redoc": "^2.0.0-rc.2",
|
||||
"swagger-ui-dist": "^3.21.0"
|
||||
"redoc": "^2.0.0-rc.8-1",
|
||||
"swagger-ui-dist": "^3.22.3"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
# test project requirements
|
||||
Pillow>=4.3.0
|
||||
pygments>=2.2.0
|
||||
django-cors-headers>=2.1.0
|
||||
django-filter>=1.1.0,<2.0; python_version == "2.7"
|
||||
django-filter>=1.1.0; python_version >= "3.4"
|
||||
django-filter>=1.1.0; python_version >= "3.5"
|
||||
djangorestframework-camel-case>=0.2.0
|
||||
djangorestframework-recursive>=0.1.2
|
||||
dj-database-url>=0.4.2
|
||||
|
||||
@@ -19,6 +19,18 @@ with io.open('README.rst', encoding='utf-8') as readme:
|
||||
requirements = read_req('base.txt')
|
||||
requirements_validation = read_req('validation.txt')
|
||||
|
||||
py3_supported_range = (5, 7)
|
||||
|
||||
# convert inclusive range to exclusive range
|
||||
py3_supported_range = (py3_supported_range[0], py3_supported_range[1] + 1)
|
||||
python_requires = ", ".join([">=2.7"] + ["!=3.{}.*".format(v) for v in range(0, py3_supported_range[0])])
|
||||
python_classifiers = [
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
] + ['Programming Language :: Python :: 3.{}'.format(v) for v in range(*py3_supported_range)]
|
||||
|
||||
|
||||
def drf_yasg_setup(**kwargs):
|
||||
setup(
|
||||
@@ -38,28 +50,21 @@ def drf_yasg_setup(**kwargs):
|
||||
author_email='cristi@cvjd.me',
|
||||
keywords='drf django django-rest-framework schema swagger openapi codegen swagger-codegen '
|
||||
'documentation drf-yasg django-rest-swagger drf-openapi',
|
||||
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
|
||||
python_requires=python_requires,
|
||||
classifiers=[
|
||||
'Intended Audience :: Developers',
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Operating System :: OS Independent',
|
||||
'Environment :: Web Environment',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Framework :: Django',
|
||||
'Framework :: Django :: 1.11',
|
||||
'Framework :: Django :: 2.0',
|
||||
'Framework :: Django :: 2.1',
|
||||
'Framework :: Django :: 2.2',
|
||||
'Topic :: Documentation',
|
||||
'Topic :: Software Development :: Code Generators',
|
||||
],
|
||||
] + python_classifiers,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
||||
@@ -272,7 +272,8 @@ class FieldInspector(BaseInspector):
|
||||
assert not isinstance(field, openapi.SwaggerDict), "passed field is already a SwaggerDict object"
|
||||
title = force_real_str(field.label) if field.label else None
|
||||
title = title if swagger_object_type == openapi.Schema else None # only Schema has title
|
||||
description = force_real_str(field.help_text) if field.help_text else None
|
||||
help_text = getattr(field, 'help_text', None)
|
||||
description = force_real_str(help_text) if help_text else None
|
||||
description = description if swagger_object_type != openapi.Items else None # Items has no description either
|
||||
|
||||
def SwaggerType(existing_object=None, **instance_kwargs):
|
||||
@@ -341,6 +342,9 @@ class ViewInspector(BaseInspector):
|
||||
#: methods that are assumed to require a request body determined by the view's ``serializer_class``
|
||||
implicit_body_methods = ('PUT', 'PATCH', 'POST')
|
||||
|
||||
#: methods which are assumed to return a list of objects when present on non-detail endpoints
|
||||
implicit_list_response_methods = ('GET',)
|
||||
|
||||
# real values set in __init__ to prevent import errors
|
||||
field_inspectors = [] #:
|
||||
filter_inspectors = [] #:
|
||||
@@ -374,20 +378,30 @@ class ViewInspector(BaseInspector):
|
||||
"""
|
||||
raise NotImplementedError("ViewInspector must implement get_operation()!")
|
||||
|
||||
# methods below provided as default implementations for probing inspectors
|
||||
def is_list_view(self):
|
||||
"""Determine whether this view is a list or a detail view. The difference between the two is that
|
||||
detail views depend on a pk/id path parameter. Note that a non-detail view does not necessarily imply a list
|
||||
reponse (:meth:`.has_list_response`), nor are list responses limited to non-detail views.
|
||||
|
||||
For example, one might have a `/topic/<pk>/posts` endpoint which is a detail view that has a list response.
|
||||
|
||||
:rtype: bool"""
|
||||
return is_list_view(self.path, self.method, self.view)
|
||||
|
||||
def has_list_response(self):
|
||||
"""Determine whether this view returns multiple objects. By default this is any non-detail view
|
||||
(see :meth:`.is_list_view`) whose request method is one of :attr:`.implicit_list_response_methods`.
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
return self.is_list_view() and (self.method.upper() in self.implicit_list_response_methods)
|
||||
|
||||
def should_filter(self):
|
||||
"""Determine whether filter backend parameters should be included for this request.
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
if not getattr(self.view, 'filter_backends', None):
|
||||
return False
|
||||
|
||||
if self.method.lower() not in ["get", "delete"]:
|
||||
return False
|
||||
|
||||
return is_list_view(self.path, self.method, self.view)
|
||||
return getattr(self.view, 'filter_backends', None) and self.has_list_response()
|
||||
|
||||
def get_filter_parameters(self):
|
||||
"""Return the parameters added to the view by its filter backends.
|
||||
@@ -408,13 +422,7 @@ class ViewInspector(BaseInspector):
|
||||
|
||||
:rtype: bool
|
||||
"""
|
||||
if not getattr(self.view, 'paginator', None):
|
||||
return False
|
||||
|
||||
if self.method.lower() != 'get':
|
||||
return False
|
||||
|
||||
return is_list_view(self.path, self.method, self.view)
|
||||
return getattr(self.view, 'paginator', None) and self.has_list_response()
|
||||
|
||||
def get_pagination_parameters(self):
|
||||
"""Return the parameters added to the view by its paginator.
|
||||
|
||||
@@ -2,6 +2,7 @@ import datetime
|
||||
import inspect
|
||||
import logging
|
||||
import operator
|
||||
import sys
|
||||
import uuid
|
||||
from collections import OrderedDict
|
||||
from decimal import Decimal
|
||||
@@ -13,7 +14,9 @@ from rest_framework.settings import api_settings as rest_framework_settings
|
||||
|
||||
from .. import openapi
|
||||
from ..errors import SwaggerGenerationError
|
||||
from ..utils import decimal_as_float, filter_none, get_serializer_class, get_serializer_ref_name
|
||||
from ..utils import (
|
||||
decimal_as_float, field_value_to_representation, filter_none, get_serializer_class, get_serializer_ref_name
|
||||
)
|
||||
from .base import FieldInspector, NotHandled, SerializerInspector, call_view_method
|
||||
|
||||
try:
|
||||
@@ -487,6 +490,10 @@ hinting_type_info = [
|
||||
(datetime.date, (openapi.TYPE_STRING, openapi.FORMAT_DATE)),
|
||||
]
|
||||
|
||||
if sys.version_info < (3, 0):
|
||||
# noinspection PyUnresolvedReferences
|
||||
hinting_type_info.append((unicode, (openapi.TYPE_STRING, None))) # noqa: F821
|
||||
|
||||
if typing:
|
||||
def inspect_collection_hint_class(hint_class):
|
||||
args = hint_class.__args__
|
||||
@@ -525,11 +532,14 @@ def get_basic_type_info_from_hint(hint_class):
|
||||
:rtype: OrderedDict
|
||||
"""
|
||||
union_types = _get_union_types(hint_class)
|
||||
|
||||
if typing and union_types:
|
||||
# Optional is implemented as Union[T, None]
|
||||
if len(union_types) == 2 and isinstance(None, union_types[1]):
|
||||
result = get_basic_type_info_from_hint(union_types[0])
|
||||
result['x-nullable'] = True
|
||||
if result:
|
||||
result['x-nullable'] = True
|
||||
|
||||
return result
|
||||
|
||||
return None
|
||||
@@ -600,9 +610,7 @@ class SerializerMethodFieldInspector(FieldInspector):
|
||||
# look for Python 3.5+ style type hinting of the return value
|
||||
hint_class = inspect_signature(method).return_annotation
|
||||
|
||||
if not inspect.isclass(hint_class) and hasattr(hint_class, '__args__'):
|
||||
hint_class = hint_class.__args__[0]
|
||||
if inspect.isclass(hint_class) and not issubclass(hint_class, inspect._empty):
|
||||
if not issubclass(hint_class, inspect._empty):
|
||||
type_info = get_basic_type_info_from_hint(hint_class)
|
||||
|
||||
if type_info is not None:
|
||||
@@ -635,7 +643,14 @@ class ChoiceFieldInspector(FieldInspector):
|
||||
|
||||
if isinstance(field, serializers.ChoiceField):
|
||||
enum_type = openapi.TYPE_STRING
|
||||
enum_values = list(field.choices.keys())
|
||||
enum_values = []
|
||||
for choice in field.choices.keys():
|
||||
if isinstance(field, serializers.MultipleChoiceField):
|
||||
choice = field_value_to_representation(field, [choice])[0]
|
||||
else:
|
||||
choice = field_value_to_representation(field, choice)
|
||||
|
||||
enum_values.append(choice)
|
||||
|
||||
# for ModelSerializer, try to infer the type from the associated model field
|
||||
serializer = get_parent_serializer(field)
|
||||
|
||||
@@ -9,7 +9,7 @@ from .. import openapi
|
||||
from ..errors import SwaggerGenerationError
|
||||
from ..utils import (
|
||||
filter_none, force_real_str, force_serializer_instance, get_consumes, get_produces, guess_response_status,
|
||||
is_list_view, merge_params, no_body, param_list_to_odict
|
||||
merge_params, no_body, param_list_to_odict
|
||||
)
|
||||
from .base import ViewInspector, call_view_method
|
||||
|
||||
@@ -208,7 +208,7 @@ class SwaggerAutoSchema(ViewInspector):
|
||||
default_schema = self.serializer_to_schema(default_schema) or ''
|
||||
|
||||
if default_schema:
|
||||
if is_list_view(self.path, self.method, self.view) and self.method.lower() == 'get':
|
||||
if self.has_list_response():
|
||||
default_schema = openapi.Schema(type=openapi.TYPE_ARRAY, items=default_schema)
|
||||
if self.should_page():
|
||||
default_schema = self.get_paginated_response(default_schema) or default_schema
|
||||
|
||||
+33
-32
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+25
-7
@@ -2,11 +2,12 @@ import inspect
|
||||
import logging
|
||||
import sys
|
||||
from collections import OrderedDict
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db import models
|
||||
from django.utils.encoding import force_text
|
||||
from rest_framework import serializers, status
|
||||
from rest_framework.mixins import DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||
from rest_framework.mixins import DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin
|
||||
from rest_framework.parsers import FileUploadParser
|
||||
from rest_framework.request import is_form_media_type
|
||||
from rest_framework.settings import api_settings as rest_framework_settings
|
||||
@@ -226,6 +227,9 @@ def is_list_view(path, method, view):
|
||||
# a detail action is surely not a list route
|
||||
return False
|
||||
|
||||
if isinstance(view, ListModelMixin):
|
||||
return True
|
||||
|
||||
# for GenericAPIView, if it's a detail view it can't also be a list view
|
||||
if isinstance(view, (RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin)):
|
||||
return False
|
||||
@@ -437,6 +441,25 @@ def force_real_str(s, encoding='utf-8', strings_only=False, errors='strict'):
|
||||
return s
|
||||
|
||||
|
||||
def field_value_to_representation(field, value):
|
||||
"""Convert a python value related to a field (default, choices, etc.) into its OpenAPI-compatible representation.
|
||||
|
||||
:param serializers.Field field: field associated with the value
|
||||
:param object value: value
|
||||
:return: the converted value
|
||||
"""
|
||||
value = field.to_representation(value)
|
||||
if isinstance(value, Decimal):
|
||||
if decimal_as_float(field):
|
||||
value = float(value)
|
||||
else:
|
||||
value = str(value)
|
||||
|
||||
# JSON roundtrip ensures that the value is valid JSON;
|
||||
# for example, sets and tuples get transformed into lists
|
||||
return json.loads(json.dumps(value, cls=encoders.JSONEncoder))
|
||||
|
||||
|
||||
def get_field_default(field):
|
||||
"""
|
||||
Get the default value for a field, converted to a JSON-compatible value while properly handling callables.
|
||||
@@ -458,12 +481,7 @@ def get_field_default(field):
|
||||
|
||||
if default is not serializers.empty and default is not None:
|
||||
try:
|
||||
default = field.to_representation(default)
|
||||
# JSON roundtrip ensures that the value is valid JSON;
|
||||
# for example, sets and tuples get transformed into lists
|
||||
default = json.loads(json.dumps(default, cls=encoders.JSONEncoder))
|
||||
if decimal_as_float(field):
|
||||
default = float(default)
|
||||
default = field_value_to_representation(field, default)
|
||||
except Exception: # pragma: no cover
|
||||
logger.warning("'default' on schema for %s will not be set because "
|
||||
"to_representation raised an exception", field, exc_info=True)
|
||||
|
||||
@@ -7,7 +7,7 @@ from rest_framework import viewsets
|
||||
# noinspection PyDeprecation
|
||||
from rest_framework.filters import OrderingFilter
|
||||
from rest_framework.pagination import LimitOffsetPagination
|
||||
from rest_framework.parsers import MultiPartParser, FileUploadParser
|
||||
from rest_framework.parsers import FileUploadParser, MultiPartParser
|
||||
from rest_framework.response import Response
|
||||
|
||||
from articles import serializers
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Generated by Django 2.1.7 on 2019-03-16 14:06
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('snippets', '0002_auto_20181219_1016'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SnippetViewer',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('snippet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='viewers', to='snippets.Snippet')),
|
||||
('viewer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='snippet_views', to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 2.2.2 on 2019-06-12 22:54
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('snippets', '0003_snippetviewer'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='snippet',
|
||||
name='language',
|
||||
field=models.CharField(choices=[('cpp', 'cpp'), ('js', 'js'), ('python', 'python')], default='python', max_length=100),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='snippet',
|
||||
name='style',
|
||||
field=models.CharField(choices=[('monokai', 'monokai'), ('solarized-dark', 'solarized-dark'), ('vim', 'vim')], default='solarized-dark', max_length=100),
|
||||
),
|
||||
]
|
||||
@@ -1,10 +1,7 @@
|
||||
from django.db import models
|
||||
from pygments.lexers import get_all_lexers
|
||||
from pygments.styles import get_all_styles
|
||||
|
||||
LEXERS = [item for item in get_all_lexers() if item[1]]
|
||||
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
|
||||
STYLE_CHOICES = sorted((item, item) for item in get_all_styles())
|
||||
LANGUAGE_CHOICES = sorted((item, item) for item in ('cpp', 'python', 'js'))
|
||||
STYLE_CHOICES = sorted((item, item) for item in ('solarized-dark', 'monokai', 'vim'))
|
||||
|
||||
|
||||
class Snippet(models.Model):
|
||||
@@ -14,7 +11,12 @@ class Snippet(models.Model):
|
||||
code = models.TextField(help_text="code model help text")
|
||||
linenos = models.BooleanField(default=False)
|
||||
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
|
||||
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
|
||||
style = models.CharField(choices=STYLE_CHOICES, default='solarized-dark', max_length=100)
|
||||
|
||||
class Meta:
|
||||
ordering = ('created',)
|
||||
|
||||
|
||||
class SnippetViewer(models.Model):
|
||||
snippet = models.ForeignKey(Snippet, on_delete=models.CASCADE, related_name='viewers')
|
||||
viewer = models.ForeignKey('auth.User', related_name='snippet_views', on_delete=models.CASCADE)
|
||||
|
||||
@@ -4,7 +4,7 @@ from django.contrib.auth import get_user_model
|
||||
from rest_framework import serializers
|
||||
from rest_framework.compat import MaxLengthValidator, MinValueValidator
|
||||
|
||||
from snippets.models import LANGUAGE_CHOICES, STYLE_CHOICES, Snippet
|
||||
from snippets.models import LANGUAGE_CHOICES, STYLE_CHOICES, Snippet, SnippetViewer
|
||||
|
||||
|
||||
class LanguageSerializer(serializers.Serializer):
|
||||
@@ -17,7 +17,7 @@ class LanguageSerializer(serializers.Serializer):
|
||||
|
||||
|
||||
class ExampleProjectSerializer(serializers.Serializer):
|
||||
project_name = serializers.CharField(help_text='Name of the project')
|
||||
project_name = serializers.CharField(label='project name custom title', help_text='Name of the project')
|
||||
github_repo = serializers.CharField(required=True, help_text='Github repository of the project')
|
||||
|
||||
class Meta:
|
||||
@@ -69,7 +69,7 @@ class SnippetSerializer(serializers.Serializer):
|
||||
tags = serializers.ListField(child=serializers.CharField(min_length=2), min_length=3, max_length=15)
|
||||
linenos = serializers.BooleanField(required=False)
|
||||
language = LanguageSerializer(help_text="Sample help text for language")
|
||||
styles = serializers.MultipleChoiceField(choices=STYLE_CHOICES, default=['friendly'])
|
||||
styles = serializers.MultipleChoiceField(choices=STYLE_CHOICES, default=['solarized-dark'])
|
||||
lines = serializers.ListField(child=serializers.IntegerField(), allow_empty=True, allow_null=True, required=False)
|
||||
example_projects = serializers.ListSerializer(child=ExampleProjectSerializer(), read_only=True,
|
||||
validators=[MaxLengthValidator(100)])
|
||||
@@ -100,3 +100,9 @@ class SnippetSerializer(serializers.Serializer):
|
||||
instance.style = validated_data.get('style', instance.style)
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class SnippetViewerSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = SnippetViewer
|
||||
fields = '__all__'
|
||||
|
||||
@@ -8,10 +8,13 @@ if django.VERSION[:2] >= (2, 0):
|
||||
urlpatterns = [
|
||||
path('', views.SnippetList.as_view()),
|
||||
path('<int:pk>/', views.SnippetDetail.as_view()),
|
||||
path('views/<int:snippet_pk>/', views.SnippetViewerList.as_view()),
|
||||
]
|
||||
else:
|
||||
from django.conf.urls import url
|
||||
|
||||
urlpatterns = [
|
||||
url('^$', views.SnippetList.as_view()),
|
||||
url(r'^(?P<pk>\d+)/$', views.SnippetDetail.as_view()),
|
||||
url(r'^views/(?P<snippet_pk>\d+)/$', views.SnippetViewerList.as_view()),
|
||||
]
|
||||
|
||||
@@ -2,13 +2,15 @@ from djangorestframework_camel_case.parser import CamelCaseJSONParser
|
||||
from djangorestframework_camel_case.render import CamelCaseJSONRenderer
|
||||
from inflection import camelize
|
||||
from rest_framework import generics, status
|
||||
from rest_framework.parsers import FormParser, FileUploadParser
|
||||
from rest_framework.generics import get_object_or_404
|
||||
from rest_framework.pagination import PageNumberPagination
|
||||
from rest_framework.parsers import FileUploadParser, FormParser
|
||||
|
||||
from drf_yasg import openapi
|
||||
from drf_yasg.inspectors import SwaggerAutoSchema
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
from snippets.models import Snippet
|
||||
from snippets.serializers import SnippetSerializer
|
||||
from snippets.models import Snippet, SnippetViewer
|
||||
from snippets.serializers import SnippetSerializer, SnippetViewerSerializer
|
||||
|
||||
|
||||
class CamelCaseOperationIDAutoSchema(SwaggerAutoSchema):
|
||||
@@ -93,3 +95,31 @@ class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||
def delete(self, request, *args, **kwargs):
|
||||
"""delete method docstring"""
|
||||
return super(SnippetDetail, self).patch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class SnippetViewerList(generics.ListAPIView):
|
||||
"""SnippetViewerList classdoc"""
|
||||
serializer_class = SnippetViewerSerializer
|
||||
pagination_class = PageNumberPagination
|
||||
|
||||
parser_classes = (FormParser, CamelCaseJSONParser, FileUploadParser)
|
||||
renderer_classes = (CamelCaseJSONRenderer,)
|
||||
swagger_schema = CamelCaseOperationIDAutoSchema
|
||||
lookup_url_kwarg = 'snippet_pk'
|
||||
|
||||
def get_object(self):
|
||||
queryset = Snippet.objects.all()
|
||||
|
||||
# Perform the lookup filtering.
|
||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||
|
||||
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
|
||||
obj = get_object_or_404(queryset, **filter_kwargs)
|
||||
|
||||
# May raise a permission denied
|
||||
self.check_object_permissions(self.request, obj)
|
||||
|
||||
return obj
|
||||
|
||||
def get_queryset(self):
|
||||
return SnippetViewer.objects.filter(snippet=self.get_object())
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
# Generated by Django 2.1.5 on 2019-04-01 00:28
|
||||
|
||||
from decimal import Decimal
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('todo', '0002_todotree'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Pack',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('size_code', models.DecimalField(choices=[(Decimal('50'), '5x10'), (Decimal('100'), '10x10'), (Decimal('200'), '10x20')], decimal_places=3, default=Decimal('200'), max_digits=7)),
|
||||
],
|
||||
),
|
||||
]
|
||||
@@ -1,3 +1,5 @@
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db import models
|
||||
|
||||
|
||||
@@ -18,3 +20,19 @@ class TodoYetAnother(models.Model):
|
||||
class TodoTree(models.Model):
|
||||
parent = models.ForeignKey('self', on_delete=models.CASCADE, related_name='children', null=True)
|
||||
title = models.CharField(max_length=50)
|
||||
|
||||
|
||||
class Pack(models.Model):
|
||||
SIZE_10x20 = Decimal(200.000)
|
||||
SIZE_10x10 = Decimal(100.000)
|
||||
SIZE_5x10 = Decimal(50.000)
|
||||
|
||||
size_code_choices = (
|
||||
(SIZE_5x10, '5x10'),
|
||||
(SIZE_10x10, '10x10'),
|
||||
(SIZE_10x20, '10x20'),
|
||||
)
|
||||
size_code = models.DecimalField(max_digits=7,
|
||||
decimal_places=3,
|
||||
choices=size_code_choices,
|
||||
default=SIZE_10x20)
|
||||
|
||||
@@ -4,7 +4,7 @@ from django.utils import timezone
|
||||
from rest_framework import serializers
|
||||
from rest_framework_recursive.fields import RecursiveField
|
||||
|
||||
from .models import Todo, TodoAnother, TodoTree, TodoYetAnother
|
||||
from .models import Pack, Todo, TodoAnother, TodoTree, TodoYetAnother
|
||||
|
||||
|
||||
class TodoSerializer(serializers.ModelSerializer):
|
||||
@@ -57,3 +57,14 @@ class TodoRecursiveSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = TodoTree
|
||||
fields = ('id', 'title', 'parent', 'parent_id')
|
||||
|
||||
|
||||
class HarvestSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = Pack
|
||||
fields = (
|
||||
'size_code',
|
||||
)
|
||||
read_only_fields = (
|
||||
'size_code',
|
||||
)
|
||||
|
||||
@@ -9,6 +9,7 @@ router.register(r'another', views.TodoAnotherViewSet)
|
||||
router.register(r'yetanother', views.TodoYetAnotherViewSet)
|
||||
router.register(r'tree', views.TodoTreeView)
|
||||
router.register(r'recursive', views.TodoRecursiveView)
|
||||
router.register(r'harvest', views.HarvestViewSet)
|
||||
|
||||
urlpatterns = router.urls
|
||||
|
||||
|
||||
+18
-3
@@ -1,11 +1,13 @@
|
||||
from rest_framework import viewsets
|
||||
from rest_framework import mixins, permissions, viewsets
|
||||
from rest_framework.authentication import TokenAuthentication
|
||||
from rest_framework.generics import RetrieveAPIView
|
||||
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
|
||||
from .models import Todo, TodoAnother, TodoTree, TodoYetAnother
|
||||
from .models import Pack, Todo, TodoAnother, TodoTree, TodoYetAnother
|
||||
from .serializer import (
|
||||
TodoAnotherSerializer, TodoRecursiveSerializer, TodoSerializer, TodoTreeSerializer, TodoYetAnotherSerializer
|
||||
HarvestSerializer, TodoAnotherSerializer, TodoRecursiveSerializer, TodoSerializer, TodoTreeSerializer,
|
||||
TodoYetAnotherSerializer
|
||||
)
|
||||
|
||||
|
||||
@@ -75,3 +77,16 @@ class TodoRecursiveView(viewsets.ModelViewSet):
|
||||
@swagger_auto_schema(responses={200: TodoRecursiveSerializer(many=True)})
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super(TodoRecursiveView, self).list(request, *args, **kwargs)
|
||||
|
||||
|
||||
class HarvestViewSet(mixins.ListModelMixin,
|
||||
mixins.UpdateModelMixin,
|
||||
viewsets.GenericViewSet):
|
||||
|
||||
queryset = Pack.objects.all()
|
||||
serializer_class = HarvestSerializer
|
||||
permission_classes = [permissions.IsAuthenticated]
|
||||
authentication_classes = [TokenAuthentication]
|
||||
|
||||
def perform_update(self, serializer):
|
||||
pass
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import sys
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from rest_framework import serializers
|
||||
|
||||
@@ -6,7 +8,10 @@ from snippets.models import Snippet
|
||||
|
||||
try:
|
||||
import typing # noqa: F401
|
||||
from .method_serializers_with_typing import MethodFieldExampleSerializer
|
||||
if sys.version_info >= (3, 4):
|
||||
from .method_serializers_with_typing import MethodFieldExampleSerializer
|
||||
else:
|
||||
from .method_serializers_without_typing import MethodFieldExampleSerializer
|
||||
except ImportError:
|
||||
from .method_serializers_without_typing import MethodFieldExampleSerializer
|
||||
|
||||
|
||||
+124
-463
@@ -440,6 +440,46 @@ paths:
|
||||
tags:
|
||||
- snippets
|
||||
parameters: []
|
||||
/snippets/views/{snippet_pk}/:
|
||||
get:
|
||||
operationId: snippetsViewsRead
|
||||
description: SnippetViewerList classdoc
|
||||
parameters:
|
||||
- name: page
|
||||
in: query
|
||||
description: A page number within the paginated result set.
|
||||
required: false
|
||||
type: integer
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
required:
|
||||
- count
|
||||
- results
|
||||
type: object
|
||||
properties:
|
||||
count:
|
||||
type: integer
|
||||
next:
|
||||
type: string
|
||||
format: uri
|
||||
x-nullable: true
|
||||
previous:
|
||||
type: string
|
||||
format: uri
|
||||
x-nullable: true
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/SnippetViewer'
|
||||
tags:
|
||||
- snippets
|
||||
parameters:
|
||||
- name: snippet_pk
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
/snippets/{id}/:
|
||||
get:
|
||||
operationId: snippetsRead
|
||||
@@ -552,6 +592,60 @@ paths:
|
||||
description: A unique integer value identifying this todo another.
|
||||
required: true
|
||||
type: integer
|
||||
/todo/harvest/:
|
||||
get:
|
||||
operationId: todo_harvest_list
|
||||
description: ''
|
||||
parameters: []
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Harvest'
|
||||
tags:
|
||||
- todo
|
||||
parameters: []
|
||||
/todo/harvest/{id}/:
|
||||
put:
|
||||
operationId: todo_harvest_update
|
||||
description: ''
|
||||
parameters:
|
||||
- name: data
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Harvest'
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/Harvest'
|
||||
tags:
|
||||
- todo
|
||||
patch:
|
||||
operationId: todo_harvest_partial_update
|
||||
description: ''
|
||||
parameters:
|
||||
- name: data
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/Harvest'
|
||||
responses:
|
||||
'200':
|
||||
description: ''
|
||||
schema:
|
||||
$ref: '#/definitions/Harvest'
|
||||
tags:
|
||||
- todo
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
description: A unique integer value identifying this pack.
|
||||
required: true
|
||||
type: integer
|
||||
/todo/recursive/:
|
||||
get:
|
||||
operationId: todo_recursive_list
|
||||
@@ -1016,7 +1110,7 @@ definitions:
|
||||
type: object
|
||||
properties:
|
||||
projectName:
|
||||
title: Project name
|
||||
title: project name custom title
|
||||
description: Name of the project
|
||||
type: string
|
||||
minLength: 1
|
||||
@@ -1082,443 +1176,9 @@ definitions:
|
||||
description: The name of the programming language
|
||||
type: string
|
||||
enum:
|
||||
- abap
|
||||
- abnf
|
||||
- ada
|
||||
- adl
|
||||
- agda
|
||||
- aheui
|
||||
- ahk
|
||||
- alloy
|
||||
- ampl
|
||||
- antlr
|
||||
- antlr-as
|
||||
- antlr-cpp
|
||||
- antlr-csharp
|
||||
- antlr-java
|
||||
- antlr-objc
|
||||
- antlr-perl
|
||||
- antlr-python
|
||||
- antlr-ruby
|
||||
- apacheconf
|
||||
- apl
|
||||
- applescript
|
||||
- arduino
|
||||
- as
|
||||
- as3
|
||||
- aspectj
|
||||
- aspx-cs
|
||||
- aspx-vb
|
||||
- asy
|
||||
- at
|
||||
- autoit
|
||||
- awk
|
||||
- basemake
|
||||
- bash
|
||||
- bat
|
||||
- bbcode
|
||||
- bc
|
||||
- befunge
|
||||
- bib
|
||||
- blitzbasic
|
||||
- blitzmax
|
||||
- bnf
|
||||
- boo
|
||||
- boogie
|
||||
- brainfuck
|
||||
- bro
|
||||
- bst
|
||||
- bugs
|
||||
- c
|
||||
- c-objdump
|
||||
- ca65
|
||||
- cadl
|
||||
- camkes
|
||||
- capdl
|
||||
- capnp
|
||||
- cbmbas
|
||||
- ceylon
|
||||
- cfc
|
||||
- cfengine3
|
||||
- cfm
|
||||
- cfs
|
||||
- chai
|
||||
- chapel
|
||||
- cheetah
|
||||
- cirru
|
||||
- clay
|
||||
- clean
|
||||
- clojure
|
||||
- clojurescript
|
||||
- cmake
|
||||
- cobol
|
||||
- cobolfree
|
||||
- coffee-script
|
||||
- common-lisp
|
||||
- componentpascal
|
||||
- console
|
||||
- control
|
||||
- coq
|
||||
- cpp
|
||||
- cpp-objdump
|
||||
- cpsa
|
||||
- cr
|
||||
- crmsh
|
||||
- croc
|
||||
- cryptol
|
||||
- csharp
|
||||
- csound
|
||||
- csound-document
|
||||
- csound-score
|
||||
- css
|
||||
- css+django
|
||||
- css+erb
|
||||
- css+genshitext
|
||||
- css+lasso
|
||||
- css+mako
|
||||
- css+mozpreproc
|
||||
- css+myghty
|
||||
- css+php
|
||||
- css+smarty
|
||||
- cucumber
|
||||
- cuda
|
||||
- cypher
|
||||
- cython
|
||||
- d
|
||||
- d-objdump
|
||||
- dart
|
||||
- delphi
|
||||
- dg
|
||||
- diff
|
||||
- django
|
||||
- docker
|
||||
- doscon
|
||||
- dpatch
|
||||
- dtd
|
||||
- duel
|
||||
- dylan
|
||||
- dylan-console
|
||||
- dylan-lid
|
||||
- earl-grey
|
||||
- easytrieve
|
||||
- ebnf
|
||||
- ec
|
||||
- ecl
|
||||
- eiffel
|
||||
- elixir
|
||||
- elm
|
||||
- emacs
|
||||
- erb
|
||||
- erl
|
||||
- erlang
|
||||
- evoque
|
||||
- extempore
|
||||
- ezhil
|
||||
- factor
|
||||
- fan
|
||||
- fancy
|
||||
- felix
|
||||
- fennel
|
||||
- fish
|
||||
- flatline
|
||||
- forth
|
||||
- fortran
|
||||
- fortranfixed
|
||||
- foxpro
|
||||
- fsharp
|
||||
- gap
|
||||
- gas
|
||||
- genshi
|
||||
- genshitext
|
||||
- glsl
|
||||
- gnuplot
|
||||
- go
|
||||
- golo
|
||||
- gooddata-cl
|
||||
- gosu
|
||||
- groff
|
||||
- groovy
|
||||
- gst
|
||||
- haml
|
||||
- handlebars
|
||||
- haskell
|
||||
- haxeml
|
||||
- hexdump
|
||||
- hlsl
|
||||
- hsail
|
||||
- html
|
||||
- html+cheetah
|
||||
- html+django
|
||||
- html+evoque
|
||||
- html+genshi
|
||||
- html+handlebars
|
||||
- html+lasso
|
||||
- html+mako
|
||||
- html+myghty
|
||||
- html+ng2
|
||||
- html+php
|
||||
- html+smarty
|
||||
- html+twig
|
||||
- html+velocity
|
||||
- http
|
||||
- hx
|
||||
- hybris
|
||||
- hylang
|
||||
- i6t
|
||||
- idl
|
||||
- idris
|
||||
- iex
|
||||
- igor
|
||||
- inform6
|
||||
- inform7
|
||||
- ini
|
||||
- io
|
||||
- ioke
|
||||
- irc
|
||||
- isabelle
|
||||
- j
|
||||
- jags
|
||||
- jasmin
|
||||
- java
|
||||
- javascript+mozpreproc
|
||||
- jcl
|
||||
- jlcon
|
||||
- js
|
||||
- js+cheetah
|
||||
- js+django
|
||||
- js+erb
|
||||
- js+genshitext
|
||||
- js+lasso
|
||||
- js+mako
|
||||
- js+myghty
|
||||
- js+php
|
||||
- js+smarty
|
||||
- jsgf
|
||||
- json
|
||||
- json-object
|
||||
- jsonld
|
||||
- jsp
|
||||
- julia
|
||||
- juttle
|
||||
- kal
|
||||
- kconfig
|
||||
- koka
|
||||
- kotlin
|
||||
- lagda
|
||||
- lasso
|
||||
- lcry
|
||||
- lean
|
||||
- less
|
||||
- lhs
|
||||
- lidr
|
||||
- lighty
|
||||
- limbo
|
||||
- liquid
|
||||
- live-script
|
||||
- llvm
|
||||
- logos
|
||||
- logtalk
|
||||
- lsl
|
||||
- lua
|
||||
- make
|
||||
- mako
|
||||
- maql
|
||||
- mask
|
||||
- mason
|
||||
- mathematica
|
||||
- matlab
|
||||
- matlabsession
|
||||
- md
|
||||
- minid
|
||||
- modelica
|
||||
- modula2
|
||||
- monkey
|
||||
- monte
|
||||
- moocode
|
||||
- moon
|
||||
- mozhashpreproc
|
||||
- mozpercentpreproc
|
||||
- mql
|
||||
- mscgen
|
||||
- mupad
|
||||
- mxml
|
||||
- myghty
|
||||
- mysql
|
||||
- nasm
|
||||
- ncl
|
||||
- nemerle
|
||||
- nesc
|
||||
- newlisp
|
||||
- newspeak
|
||||
- ng2
|
||||
- nginx
|
||||
- nim
|
||||
- nit
|
||||
- nixos
|
||||
- nsis
|
||||
- numpy
|
||||
- nusmv
|
||||
- objdump
|
||||
- objdump-nasm
|
||||
- objective-c
|
||||
- objective-c++
|
||||
- objective-j
|
||||
- ocaml
|
||||
- octave
|
||||
- odin
|
||||
- ooc
|
||||
- opa
|
||||
- openedge
|
||||
- pacmanconf
|
||||
- pan
|
||||
- parasail
|
||||
- pawn
|
||||
- perl
|
||||
- perl6
|
||||
- php
|
||||
- pig
|
||||
- pike
|
||||
- pkgconfig
|
||||
- plpgsql
|
||||
- postgresql
|
||||
- postscript
|
||||
- pot
|
||||
- pov
|
||||
- powershell
|
||||
- praat
|
||||
- prolog
|
||||
- properties
|
||||
- protobuf
|
||||
- ps1con
|
||||
- psql
|
||||
- pug
|
||||
- puppet
|
||||
- py3tb
|
||||
- pycon
|
||||
- pypylog
|
||||
- pytb
|
||||
- python
|
||||
- python3
|
||||
- qbasic
|
||||
- qml
|
||||
- qvto
|
||||
- racket
|
||||
- ragel
|
||||
- ragel-c
|
||||
- ragel-cpp
|
||||
- ragel-d
|
||||
- ragel-em
|
||||
- ragel-java
|
||||
- ragel-objc
|
||||
- ragel-ruby
|
||||
- raw
|
||||
- rb
|
||||
- rbcon
|
||||
- rconsole
|
||||
- rd
|
||||
- rebol
|
||||
- red
|
||||
- redcode
|
||||
- registry
|
||||
- resource
|
||||
- rexx
|
||||
- rhtml
|
||||
- rnc
|
||||
- roboconf-graph
|
||||
- roboconf-instances
|
||||
- robotframework
|
||||
- rql
|
||||
- rsl
|
||||
- rst
|
||||
- rts
|
||||
- rust
|
||||
- sas
|
||||
- sass
|
||||
- sc
|
||||
- scala
|
||||
- scaml
|
||||
- scheme
|
||||
- scilab
|
||||
- scss
|
||||
- shen
|
||||
- silver
|
||||
- slim
|
||||
- smali
|
||||
- smalltalk
|
||||
- smarty
|
||||
- sml
|
||||
- snobol
|
||||
- snowball
|
||||
- sourceslist
|
||||
- sp
|
||||
- sparql
|
||||
- spec
|
||||
- splus
|
||||
- sql
|
||||
- sqlite3
|
||||
- squidconf
|
||||
- ssp
|
||||
- stan
|
||||
- stata
|
||||
- swift
|
||||
- swig
|
||||
- systemverilog
|
||||
- tads3
|
||||
- tap
|
||||
- tasm
|
||||
- tcl
|
||||
- tcsh
|
||||
- tcshcon
|
||||
- tea
|
||||
- termcap
|
||||
- terminfo
|
||||
- terraform
|
||||
- tex
|
||||
- text
|
||||
- thrift
|
||||
- todotxt
|
||||
- trac-wiki
|
||||
- treetop
|
||||
- ts
|
||||
- tsql
|
||||
- turtle
|
||||
- twig
|
||||
- typoscript
|
||||
- typoscriptcssdata
|
||||
- typoscripthtmldata
|
||||
- urbiscript
|
||||
- vala
|
||||
- vb.net
|
||||
- vcl
|
||||
- vclsnippets
|
||||
- vctreestatus
|
||||
- velocity
|
||||
- verilog
|
||||
- vgl
|
||||
- vhdl
|
||||
- vim
|
||||
- wdiff
|
||||
- whiley
|
||||
- x10
|
||||
- xml
|
||||
- xml+cheetah
|
||||
- xml+django
|
||||
- xml+erb
|
||||
- xml+evoque
|
||||
- xml+lasso
|
||||
- xml+mako
|
||||
- xml+myghty
|
||||
- xml+php
|
||||
- xml+smarty
|
||||
- xml+velocity
|
||||
- xorg.conf
|
||||
- xquery
|
||||
- xslt
|
||||
- xtend
|
||||
- xul+mozpreproc
|
||||
- yaml
|
||||
- yaml+jinja
|
||||
- zephir
|
||||
default: python
|
||||
readOnlyNullable:
|
||||
title: Read only nullable
|
||||
@@ -1531,37 +1191,11 @@ definitions:
|
||||
items:
|
||||
type: string
|
||||
enum:
|
||||
- abap
|
||||
- algol
|
||||
- algol_nu
|
||||
- arduino
|
||||
- autumn
|
||||
- borland
|
||||
- bw
|
||||
- colorful
|
||||
- default
|
||||
- emacs
|
||||
- friendly
|
||||
- fruity
|
||||
- igor
|
||||
- lovelace
|
||||
- manni
|
||||
- monokai
|
||||
- murphy
|
||||
- native
|
||||
- paraiso-dark
|
||||
- paraiso-light
|
||||
- pastie
|
||||
- perldoc
|
||||
- rainbow_dash
|
||||
- rrt
|
||||
- tango
|
||||
- trac
|
||||
- solarized-dark
|
||||
- vim
|
||||
- vs
|
||||
- xcode
|
||||
default:
|
||||
- friendly
|
||||
- solarized-dark
|
||||
lines:
|
||||
type: array
|
||||
items:
|
||||
@@ -1590,6 +1224,22 @@ definitions:
|
||||
format: decimal
|
||||
default: 0.0
|
||||
minimum: 0.0
|
||||
SnippetViewer:
|
||||
required:
|
||||
- snippet
|
||||
- viewer
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
title: ID
|
||||
type: integer
|
||||
readOnly: true
|
||||
snippet:
|
||||
title: Snippet
|
||||
type: integer
|
||||
viewer:
|
||||
title: Viewer
|
||||
type: integer
|
||||
Todo:
|
||||
required:
|
||||
- title
|
||||
@@ -1613,6 +1263,17 @@ definitions:
|
||||
minLength: 1
|
||||
todo:
|
||||
$ref: '#/definitions/Todo'
|
||||
Harvest:
|
||||
type: object
|
||||
properties:
|
||||
size_code:
|
||||
title: Size code
|
||||
type: string
|
||||
enum:
|
||||
- '50'
|
||||
- '100'
|
||||
- '200'
|
||||
readOnly: true
|
||||
TodoRecursive:
|
||||
required:
|
||||
- title
|
||||
|
||||
@@ -204,6 +204,7 @@ def test_action_mapping():
|
||||
|
||||
@pytest.mark.parametrize('choices, expected_type', [
|
||||
(['A', 'B'], openapi.TYPE_STRING),
|
||||
([u'A', u'B'], openapi.TYPE_STRING),
|
||||
([123, 456], openapi.TYPE_INTEGER),
|
||||
([1.2, 3.4], openapi.TYPE_NUMBER),
|
||||
(['A', 456], openapi.TYPE_STRING)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
[tox]
|
||||
minversion = 3.3.0
|
||||
isolated_build = true
|
||||
isolated_build_env=.package
|
||||
isolated_build_env = .package
|
||||
|
||||
# https://docs.djangoproject.com/en/dev/faq/install/#what-python-version-can-i-use-with-django
|
||||
envlist =
|
||||
py{27,34,35,36}-django111-drf{37,38,39},
|
||||
py{34,35,36,37}-django20-drf{37,38,39},
|
||||
py{35,36,37}-django21-drf{37,38,39},
|
||||
py27-django111-drf39-typing,
|
||||
py{27,35,36}-django111-drf{37,38,39},
|
||||
py{35,36,37}-django{20,21,22}-drf{37,38,39},
|
||||
djmaster, lint, docs
|
||||
|
||||
[testenv:.package]
|
||||
@@ -19,11 +19,14 @@ deps =
|
||||
django111: Django>=1.11,<2.0
|
||||
django20: Django>=2.0,<2.1
|
||||
django21: Django>=2.1,<2.2
|
||||
django22: Django>=2.2,<2.3
|
||||
|
||||
drf37: djangorestframework>=3.7.7,<3.8
|
||||
drf38: djangorestframework>=3.8.0,<3.9
|
||||
drf39: djangorestframework>=3.9,<3.10
|
||||
|
||||
typing: typing>=3.6.6
|
||||
|
||||
# test with the latest build of django-rest-framework to get early warning of compatibility issues
|
||||
djmaster: https://github.com/encode/django-rest-framework/archive/master.tar.gz
|
||||
djmaster: https://github.com/django/django/archive/master.tar.gz
|
||||
@@ -72,6 +75,6 @@ known_standard_library =
|
||||
types,warnings
|
||||
known_third_party =
|
||||
coreapi,coreschema,datadiff,dj_database_url,django,django_filters,djangorestframework_camel_case,
|
||||
rest_framework_recursive,flex,gunicorn,inflection,pygments,pytest,rest_framework,ruamel,setuptools_scm,
|
||||
rest_framework_recursive,flex,gunicorn,inflection,pytest,rest_framework,ruamel,setuptools_scm,
|
||||
swagger_spec_validator,uritemplate,user_agents,whitenoise,oauth2_provider
|
||||
known_first_party = drf_yasg,testproj,articles,people,snippets,todo,users,urlconfs
|
||||
|
||||
Reference in New Issue
Block a user