-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of https://github.com/mission-liao/pyswagger
- Loading branch information
Showing
16 changed files
with
264 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
The initialization of pyswagger starts from **SwaggerApp.\_create_(url)**, where **url** could either be a _url_ or a _file_ path. This function returns a SwaggerApp instance, which would be used to initiate SwaggerSecurity. | ||
|
||
**SwaggerApp.op** provides a shortcut to access Operation objects, which will produce a set of request/response for SwaggerClient to access API. The way we provide here would help to minimize the possible difference introduced by Swagger2.0 when everything is merged into one file. | ||
```python | ||
# call an API when its nickname is unique | ||
SwaggerApp.op['getPetById'] | ||
# call an API when its nickname collid with other resources | ||
SwaggerApp.op['user', 'getById'] # operationId:'getById', tags:'user' (or a user resource in Swagger 1.2) | ||
SwaggerApp.op['pet', 'getById'] # operationId:'getById', tags:'pet' (or a pet resource in Swagger 1.2) | ||
|
||
# utilize SwaggerApp.resolve to do the same thing | ||
SwaggerApp.resolve('#/paths/~1pet~1{petId}').get | ||
# instead of writing JSON-pointers by yourselves, utilize pyswagger.utils.jp_compose | ||
SwaggerApp.resolve(utils.jp_compose('/pet/{petId}', base='#/paths')).get | ||
``` | ||
**SwaggerApp.validate(strict=True)** provides validation against the loaded Swagger API definition. When passing _strict=True_, an exception would be raised if validation failed. It returns a list of errors in tuple: _(where, type, msg)_. | ||
|
||
**SwaggerApp.resolve(JSON_Reference)** is a new way to access objects. For example, to access a Schema object 'User': | ||
```python | ||
app.resolve('#/definitions/User') | ||
``` | ||
This function accepts a [JSON Reference](http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03), which is composed by an url and a [JSON Pointer](http://tools.ietf.org/html/rfc6901), it is the standard way to access a Swagger document. Since a JSON reference contains an url, this means you can access any external document when you need: | ||
```python | ||
app.resolve('http://another_site.com/apis/swagger.json#/definitions/User') | ||
``` | ||
`pyswagger` will load that swagger.json, create a new `SwaggerApp`, and group it with the `SwaggerApp` you kept (**app** in code above). Internally, when `pyswagger` encounter some $ref directs to external documents, we just silently handle it in the same way. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
You also need **SwaggerClient(security=None)** to access API, this layer wraps the difference between those http libraries in python. where **security**(optional) is `SwaggerSecurity`, which helps to handle authorizations of each request. | ||
|
||
```python | ||
client.request(app.op['addPet'](body=dict(id=1, name='Tom'))) | ||
``` | ||
To make a request, you need to create a pair of request/response from **SwaggerApp.op** by providing essential parameters. Then passing the tuple of (request, response) to **SwaggerClient.request(req_and_resp, opt={})** likes the code segment above. Below is a reference mapping between python objects and Swagger primitives. Check this mapping when you need to construct a parameter set: | ||
- **dict** corresponds to _Model_ | ||
- **list** corresponds to _Array_ | ||
- **datetime.datetime**, timestamp(float or int), or ISO8601-string for _date-time_ and _date_ | ||
- _File_ type is a little bit complex, but just similar to [request](https://github.com/kennethreitz/requests), which uses a dict containing file info. | ||
```python | ||
YouFile = { | ||
# header values used in multipart/form-data according to RFC2388 | ||
'header': { | ||
'Content-Type': 'text/plain', | ||
|
||
# according to RFC2388, available values are '7bit', '8bit', 'binary' | ||
'Content-Transfer-Encoding': 'binary' | ||
}, | ||
'filename': 'a.txt', | ||
'data': None (or any file-like object) | ||
} | ||
``` | ||
- other primitives are similar to python's primitives | ||
|
||
The return value is a **SwaggerResponse** object, with these attributes: | ||
- status | ||
- data, corresponds to Operation object's return value, or `ResponseMessage` object's _responseModel_ (in Swagger 1.2, `Schema` object of `Response` object in Swagger 2.0) when its status matched. | ||
- header, organized in ```{key: [value1, value2...]}``` | ||
- message, corresponds to ResponseMessage object's _message_ when status matched on ResponseMessage object. | ||
- raw, raw data without touching. | ||
|
||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
Holder/Dispatcher for user-provided authorization info. Initialize this object like **SwaggerSecurity(app)**, where **app** is an instance of SwaggerApp. To add authorization, call **SwaggerSecurity.update\_with(name, token)**, where **name** is the name of Authorizations object in Swagger 1.2(Security Scheme Object in Swagger 2.0) , and **token** is different for different kinds of authorizations: | ||
- basic authorization: (username, password) | ||
- api key: the api key | ||
- oauth2: the access\_token | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
## Initialzation | ||
|
||
The first step to use pyswagger is creating a pyswagger.SwaggerApp object. You need to provide the path of the resource file. For example, a SwaggerApp for petstore can be initialized in this way: | ||
```python | ||
from pyswagger import SwaggerApp | ||
|
||
# utilize SwaggerApp.create | ||
app = SwaggerApp.create('http://petstore.swagger.io/v2/swagger.json') | ||
``` | ||
|
||
## Initailize with A Local file | ||
|
||
The path could be an URI or a absolute path. For example, a path /home/workspace/local/swagger.json could be passed like: | ||
```python | ||
from pyswagger import SwaggerApp | ||
|
||
# file URI | ||
app = SwaggerApp.create('file:///home/workspace/local/swagger.json') | ||
# with hostname | ||
app = SwaggerApp.create('file://localhost/home/workspace/local/swagger.json') | ||
# absolute path | ||
app = SwaggerApp.create('/home/workspace/local/swagger.json') | ||
# without the file name, because 'swagger.json' is a predefined name | ||
app = SwaggerApp.create('/home/workspace/local') | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
## Testing a Local Server | ||
|
||
As a backend developer, you will need to test your API before shipping. We provide a simple way to patch the url before client actually making a request | ||
|
||
```python | ||
from pyswagger import SwaggerApp | ||
from pyswagger.contrib.client.request import Client | ||
|
||
# create a SwaggerApp with a local resource file | ||
app = SwaggerApp.create('/path/to/your/resource/file/swagger.json') | ||
# init the client | ||
client = Client() | ||
|
||
# try to making a request | ||
client.request( | ||
app.op['getUserByName'](username='Tom'), | ||
opt=dict( | ||
url_netloc='localhost:8001' # patch the url of petstore to localhost:8001 | ||
)) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
## Making a Request | ||
|
||
Three parts are involved with making a request: | ||
- access the Operation object | ||
- provide parameters to the Operation object, it will return (SwaggerRequest, SwaggerResponse) pair | ||
- provide this pair to the client implementation you choose | ||
|
||
### Access Operation | ||
There are many ways to access an Operation object. For example, if you want to access 'getUserByName' in petstore. | ||
```python | ||
from pyswagger import SwaggerApp | ||
|
||
app = SwaggerApp.create('http://petstore.swagger.io/v2/swagger.json') | ||
|
||
# via operationId and tag, they are optional in swagger 2.0 | ||
op = app.op['getUserByName'] # when the operationId is unique | ||
op = app.op['user', 'getUserByName'] # tag + operationId | ||
|
||
# via JSON Pointer, every object in Swagger can be referenced via its JSON Pointer. | ||
# The JSON pointer of Operation 'getUserByName' is '#/paths/~1user~1{username}/get', | ||
# here we provide a simple way for you to handle JSON pointer. | ||
from pyswagger import utils | ||
# check the place of the Operation 'getUserByName' in petstore | ||
op = app.resolve(utils.jp_compose(['#', 'paths', '/user/{username}', 'get'])) | ||
|
||
# cascade resolving | ||
username_api = app.resolve(utils.jp_compose(['#', 'paths', '/user/{username}'])) | ||
op = username_api.resolve('get') | ||
# there is no special character in 'get', | ||
# just access it like a property | ||
op = username_api.get | ||
``` | ||
|
||
### Provide parameter | ||
This step involves converting primitives in python to primitives in Swagger, | ||
please refer to [here](https://github.com/swagger-api/swagger-spec/blob/master/versions/2.0.md#data-types) for a list of primitives im Swagger. | ||
```python | ||
# a fake operation containing all types of primitives | ||
op = app.op['FakeApi'] | ||
|
||
req_and_resp = op( | ||
# integer, long, | ||
Id=1, | ||
# float, double | ||
speed=27.3, | ||
# string | ||
name='Tom', | ||
# byte | ||
raw=b'fffffffffff', | ||
# byte, in string, would be encoded to 'utf-8' | ||
raw_s='jdkjldkjlsdfs', | ||
# boolean | ||
like_suki=True, | ||
# date, datetime, in timestamp | ||
next_date_1=0.0, | ||
# date, in datetime.date | ||
next_date_2=datetime.date.today(), | ||
# datetime, in datetime.datetime | ||
next_date_3=datetime.datetime.now(), | ||
# date, in string ISO8601 | ||
next_date_4='2007-04-05', | ||
# datetime, in string ISO8601 | ||
next_date_5='2007-04-05T12:30:00-02:00', | ||
# array of integer | ||
list_of_ids=[1, 2, 3, 4, 5], | ||
# an object | ||
user=dict(id=1, username='Tom'), | ||
# list of objects | ||
users=[ | ||
dict(id=1, username='Tom'), | ||
dict(id=2, username='Mary') | ||
] | ||
) | ||
``` | ||
### Pass result to Client | ||
The return value when calling an Operation is a pair of (SwaggerRequest, SwaggerResponse), | ||
just pass it to 'request' function of client. Below is a full example of 'getUserByName' | ||
```python | ||
from pyswagger import SwaggerApp | ||
from pyswagger.contrib.client.request import Client | ||
|
||
app = SwaggerApp.create('/path/to/your/resource/file/swagger.json') | ||
client = Client() | ||
|
||
# make the request | ||
response = client.request( | ||
app.op['getUserByName']( # access the Operation | ||
username='Tom' # provide the parameter | ||
)) | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
## Access the Response | ||
The return value of 'request' function of each client implementation is a pyswagger.io.SwaggerResponse object. | ||
You need to access the result of your request via its interface | ||
|
||
```python | ||
from pyswagger import SwaggerApp | ||
from pyswagger.contrib.client.requests import Client | ||
|
||
app = SwaggerApp.create('/path/to/your/resource/file/swagger.json') | ||
client = Client() | ||
|
||
# making a request | ||
resp = client.request(app.op['getUserByName'](username='Tom')) | ||
|
||
# Status | ||
assert resp.status == 200 | ||
|
||
# Data | ||
# it should return a data accord with '#/definitions/User' Schema object | ||
assert resp.data.id == 1 | ||
assert resp.data.username == 'Tom' | ||
# Raw | ||
assert resp.raw == '{"id": 1, "username": "Tom"}' | ||
|
||
# Header | ||
# header is a dict, its values are lists of values, | ||
# because keys in HTTP header allow duplication. | ||
# | ||
# when the input header is: | ||
# A: 1, | ||
# A: 2, | ||
# B, 1 | ||
assert sorted(resp.header['A']) == [1, 2] | ||
assert resp.header['B'] == [1] | ||
``` |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.