Add suport for Response schemas (#10)

Schemas generated from Serializers will now be added to the `definitions` section by default, and used as `$ref` objects where needed.  
The Schema definition name is based on the serializer class name, and can be overriden by specifying a `__ref_name__` property on the Serializer. If this property is set to None, the schema will not be added to `definitions` and will be forced inline.

Closes #6, #7.
This commit is contained in:
Cristi Vîjdea
2017-12-10 03:06:49 +01:00
committed by GitHub
parent 53b2560063
commit bfced82ae4
23 changed files with 1637 additions and 273 deletions
+4 -4
View File
@@ -29,8 +29,8 @@ def codec_yaml():
@pytest.fixture
def swagger_dict():
swagger = generator().get_schema(None, True)
json_bytes = codec_yaml().encode(swagger)
return yaml.safe_load(json_bytes.decode('utf-8'))
json_bytes = codec_json().encode(swagger)
return json.loads(json_bytes.decode('utf-8'))
@pytest.fixture
@@ -60,5 +60,5 @@ def bad_settings():
@pytest.fixture
def reference_schema():
with open(os.path.join(os.path.dirname(__file__), 'reference.json')) as reference:
return json.load(reference)
with open(os.path.join(os.path.dirname(__file__), 'reference.yaml')) as reference:
return yaml.safe_load(reference)
File diff suppressed because one or more lines are too long
+971
View File
@@ -0,0 +1,971 @@
swagger: '2.0'
info:
title: Snippets API
description: Test description
termsOfService: https://www.google.com/policies/terms/
contact:
email: contact@snippets.local
license:
name: BSD License
version: v1
host: test.local:8002
schemes:
- http
basePath: /
paths:
/articles/:
get:
operationId: articles_list
description: ArticleViewSet class docstring
parameters:
- name: title
in: query
description: ''
required: false
type: string
- name: ordering
in: query
description: Which field to use when ordering the results.
required: false
type: string
- name: limit
in: query
description: Number of results to return per page.
required: false
type: integer
- name: offset
in: query
description: The initial index from which to return the results.
required: false
type: integer
responses:
'200':
description: ''
schema:
required:
- count
- results
type: object
properties:
count:
type: integer
next:
type: string
format: uri
previous:
type: string
format: uri
results:
type: array
items:
$ref: '#/definitions/Article'
consumes:
- application/json
tags:
- articles
post:
operationId: articles_create
description: ArticleViewSet class docstring
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/Article'
responses:
'201':
description: ''
schema:
$ref: '#/definitions/Article'
consumes:
- application/json
tags:
- articles
parameters: []
/articles/today/:
get:
operationId: articles_today
description: ArticleViewSet class docstring
parameters:
- name: title
in: query
description: ''
required: false
type: string
- name: ordering
in: query
description: Which field to use when ordering the results.
required: false
type: string
responses:
'200':
description: ''
schema:
type: array
items:
$ref: '#/definitions/Article'
consumes:
- application/json
tags:
- articles
parameters: []
/articles/{slug}/:
get:
operationId: articles_read
description: retrieve class docstring
parameters: []
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Article'
consumes:
- application/json
tags:
- articles
put:
operationId: articles_update
description: update method docstring
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/Article'
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Article'
consumes:
- application/json
tags:
- articles
delete:
operationId: articles_delete
description: destroy method docstring
parameters: []
responses:
'204':
description: ''
consumes:
- application/json
tags:
- articles
patch:
operationId: articles_partial_update
description: partial_update description override
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/Article'
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Article'
'404':
description: slug not found
consumes:
- application/json
tags:
- articles
parameters:
- name: slug
in: path
description: slug model help_text
required: true
type: string
pattern: '[a-z0-9]+(?:-[a-z0-9]+)'
/articles/{slug}/image/:
get:
operationId: articles_image_read
description: image GET description override
parameters: []
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Article'
consumes:
- multipart/form-data
tags:
- articles
post:
operationId: articles_image_create
description: image method docstring
parameters:
- name: upload
in: formData
description: image serializer help_text
required: true
type: file
responses:
'200':
description: success
consumes:
- multipart/form-data
tags:
- articles
parameters:
- name: slug
in: path
description: slug model help_text
required: true
type: string
pattern: '[a-z0-9]+(?:-[a-z0-9]+)'
/snippets/:
get:
operationId: snippets_list
description: SnippetList classdoc
parameters: []
responses:
'200':
description: ''
schema:
type: array
items:
$ref: '#/definitions/Snippet'
consumes:
- application/json
tags:
- snippets
post:
operationId: snippets_create
description: post method docstring
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/Snippet'
responses:
'201':
description: ''
schema:
$ref: '#/definitions/Snippet'
consumes:
- application/json
tags:
- snippets
parameters: []
/snippets/{id}/:
get:
operationId: snippets_read
description: SnippetDetail classdoc
parameters: []
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Snippet'
consumes:
- application/json
tags:
- snippets
put:
operationId: snippets_update
description: put class docstring
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/Snippet'
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Snippet'
consumes:
- application/json
tags:
- snippets
delete:
operationId: snippets_delete
description: delete method docstring
parameters: []
responses:
'204':
description: ''
consumes:
- application/json
tags:
- snippets
patch:
operationId: snippets_partial_update
description: patch method docstring
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/Snippet'
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Snippet'
consumes:
- application/json
tags:
- snippets
parameters:
- name: id
in: path
description: A unique integer value identifying this snippet.
required: true
type: integer
/users/:
get:
operationId: users_list
description: UserList cbv classdoc
parameters: []
responses:
'200':
description: ''
schema:
type: array
items:
$ref: '#/definitions/User'
consumes:
- application/json
tags:
- users
post:
operationId: users_create
description: apiview post description override
parameters:
- name: data
in: body
required: true
schema: &id001
required:
- username
type: object
properties:
username:
type: string
responses:
'201':
description: ''
schema: *id001
consumes:
- application/json
tags:
- users
patch:
operationId: users_partial_update
description: dummy operation
parameters: []
responses:
'200':
description: ''
consumes:
- application/json
tags:
- users
parameters: []
/users/{id}/:
get:
operationId: users_read
description: user_detail fbv docstring
parameters:
- name: test
in: query
description: test manual param
type: boolean
responses:
'200':
description: response description
schema:
$ref: '#/definitions/User'
consumes:
- application/json
tags:
- users
put:
operationId: users_update
description: user_detail fbv docstring
parameters:
- name: data
in: body
required: true
schema:
$ref: '#/definitions/User'
responses:
'200':
description: ''
schema:
$ref: '#/definitions/User'
consumes:
- application/json
tags:
- users
parameters:
- name: id
in: path
required: true
type: string
definitions:
Article:
required:
- title
- body
type: object
properties:
title:
description: title model help_text
type: string
body:
description: body serializer help_text
type: string
slug:
description: slug model help_text
type: string
format: slug
date_created:
type: string
format: date-time
readOnly: true
date_modified:
type: string
format: date-time
readOnly: true
Project:
required:
- project_name
- github_repo
type: object
properties:
project_name:
description: Name of the project
type: string
github_repo:
description: Github repository of the project
type: string
Snippet:
required:
- code
- language
- example_projects
type: object
properties:
id:
description: id serializer help text
type: integer
readOnly: true
owner:
type: string
readOnly: true
title:
type: string
code:
type: string
linenos:
type: boolean
language:
description: Sample help text for language
type: object
properties:
name:
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
- 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
- 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
- xquery
- xslt
- xtend
- xul+mozpreproc
- yaml
- yaml+jinja
- zephir
style:
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
- vim
- vs
- xcode
lines:
type: array
items:
type: integer
example_projects:
type: array
items:
$ref: '#/definitions/Project'
User:
required:
- username
- snippets
type: object
properties:
id:
type: integer
readOnly: true
username:
description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
only.
type: string
snippets:
type: array
items:
type: string
uniqueItems: true
securityDefinitions:
basic:
type: basic
+12 -1
View File
@@ -1,2 +1,13 @@
from datadiff.tools import assert_equal
def test_reference_schema(swagger_dict, reference_schema):
return swagger_dict == reference_schema
# formatted better than pytest diff
swagger_dict = dict(swagger_dict)
reference_schema = dict(reference_schema)
ignore = ['info', 'host', 'schemes', 'basePath', 'securityDefinitions']
for attr in ignore:
swagger_dict.pop(attr, None)
reference_schema.pop(attr, None)
assert_equal(swagger_dict, reference_schema)
+45
View File
@@ -0,0 +1,45 @@
import pytest
from drf_swagger.openapi import ReferenceResolver
def test_basic():
scopes = ['s1', 's2']
rr = ReferenceResolver(*scopes)
assert scopes == rr.scopes == list(rr.keys()) == list(rr)
rr.set('o1', 1, scope='s1')
assert rr.has('o1', scope='s1')
assert rr.get('o1', scope='s1') == 1
rr.setdefault('o1', lambda: 2, scope='s1')
assert rr.get('o1', scope='s1') == 1
assert not rr.has('o1', scope='s2')
rr.setdefault('o3', lambda: 3, scope='s2')
assert rr.get('o3', scope='s2') == 3
assert rr['s1'] == {'o1': 1}
assert dict(rr) == {'s1': {'o1': 1}, 's2': {'o3': 3}}
assert str(rr) == str(dict(rr))
def test_scoped():
scopes = ['s1', 's2']
rr = ReferenceResolver(*scopes)
r1 = rr.with_scope('s1')
r2 = rr.with_scope('s2')
with pytest.raises(AssertionError):
rr.with_scope('bad')
assert r1.scopes == ['s1']
assert list(r1.keys()) == list(r1) == []
r2.set('o2', 2)
assert r2.scopes == ['s2']
assert list(r2.keys()) == list(r2) == ['o2']
assert r2['o2'] == 2
with pytest.raises(AssertionError):
r2.get('o2', scope='s1')
assert rr.get('o2', scope='s2') == 2
+3 -2
View File
@@ -39,5 +39,6 @@ def test_json_codec_roundtrip(codec_json, generator, validate_schema):
def test_yaml_codec_roundtrip(codec_yaml, generator, validate_schema):
swagger = generator.get_schema(None, True)
json_bytes = codec_yaml.encode(swagger)
validate_schema(yaml.safe_load(json_bytes.decode('utf-8')))
yaml_bytes = codec_yaml.encode(swagger)
assert b'omap' not in yaml_bytes
validate_schema(yaml.safe_load(yaml_bytes.decode('utf-8')))