Skip to content

Commit

Permalink
Merge branch 'master' into 390-support-envelope-in-swagger
Browse files Browse the repository at this point in the history
  • Loading branch information
tnt-dev authored Nov 6, 2019
2 parents e9b5459 + d4ace9c commit abc4a8d
Show file tree
Hide file tree
Showing 41 changed files with 735 additions and 130 deletions.
44 changes: 44 additions & 0 deletions .github/ISSUE_TEMPLATE/bug-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
name: Bug Report
about: Tell us how Flask-RESTPlus is broken
title: ''
labels: bug
assignees: ''

---

### ***** **BEFORE LOGGING AN ISSUE** *****

- Is this something you can **debug and fix**? Send a pull request! Bug fixes and documentation fixes are welcome.
- Please check if a similar issue already exists or has been closed before. Seriously, nobody here is getting paid. Help us out and take five minutes to make sure you aren't submitting a duplicate.
- Please review the [guidelines for contributing](https://github.com/noirbizarre/flask-restplus/blob/master/CONTRIBUTING.rst)

### **Code**

```python
from your_code import your_buggy_implementation
```

### **Repro Steps** (if applicable)
1. ...
2. ...
3. Broken!

### **Expected Behavior**
A description of what you expected to happen.

### **Actual Behavior**
A description of the unexpected, buggy behavior.

### **Error Messages/Stack Trace**
If applicable, add the stack trace produced by the error

### **Environment**
- Python version
- Flask version
- Flask-RESTPlus version
- Other installed Flask extensions

### **Additional Context**

This is your last chance to provide any pertinent details, don't let this opportunity pass you by!
25 changes: 25 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## Proposed changes

At a high level, describe your reasoning for making these changes. If you are fixing a bug or resolving a feature request, **please include a link to the issue**.

## Types of changes

What types of changes does your code introduce?
_Put an `x` in the boxes that apply_

- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)

## Checklist

_Put an `x` in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code._

- [ ] I have read the [guidelines for contributing](https://github.com/noirbizarre/flask-restplus/blob/master/CONTRIBUTING.rst)
- [ ] All unit tests pass on my local version with my changes
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] I have added necessary documentation (if appropriate)

## Further comments

If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...
16 changes: 13 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
language: python

python:
- 2.7
- 3.4
- 3.5
- 3.6
- 3.7
- pypy
- pypy3

matrix:
include:
- python: 3.8-dev
dist: xenial
allow_failures:
- python: pypy3
- python: 3.8-dev

install:
- pip install .[dev]

script:
- inv cover qa

after_success:
- pip install coveralls
- coveralls --rcfile=coverage.rc
- ./travis-bench-after-success.sh
matrix:
allow_failures:
- python: pypy3
10 changes: 9 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@ Changelog
Current
-------

- Ensure that exceptions raised in error handler, including programming errors, are logged (:issue:`705`, :pr:`706`)
- Import the ABCs from 'collections.abc' instead of 'collections' by default as it is deprecated since Python3.7, and in 3.8 it will stop working. Python2.7 is still supported though.
- Fix illegal characters in JSON references to model names (:issue:`651`)
- Support ``envelope`` parameter in Swagger documentation (:pr:`390`)

0.13.0 (2019-08-12)
-------------------

- Add new `Wildcard` fields (:pr:`255`)
- Fix ABC deprecation warnings (:pr:`580`)
- Fix `@api.expect(..., validate=False)` decorators for an :class:`Api` where `validate=True` is set on the constructor (:issue:`609`, :pr:`610`)
- Ensure `basePath` is always a path
- Hide Namespaces with all hidden Resources from Swagger documentation
- Per route Swagger documentation for multiple routes on a ``Resource``
- Support ``envelope`` parameter in Swagger documentation (:pr:`390`)
- Fix Swagger `duplicate mapping key` problem from conflicts between response codes given as string or integer (:issue`661`)

0.12.1 (2018-09-28)
-------------------
Expand Down
4 changes: 2 additions & 2 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ If you want to contribute some code:
4. do your work in it
5. Commit your changes. Ensure the commit message includes the issue. Also, if contributing from a corporation, be sure to add a comment with the Copyright information
6. rebase it on the master branch from the official repository (cleanup your history by performing an interactive rebase)
7. add you change to the changelog
7. add your change to the changelog
8. submit your pull-request
9. 2 Maintainers should review the code for bugfix and features. 1 maintainer for minor changes (such as docs)
10. After review, a maintainer a will merge the PR. Maintainers should not merge their own PRs
Expand Down Expand Up @@ -117,4 +117,4 @@ If you're a part of a corporation with an NDA, you may be required to update the
3. When making a commit, add the specific copyright notice.

Double check with your legal department about their regulations. Not all changes
constitute new or unique work.
constitute new or unique work.
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ Flask-RESTPlus with Flask.
errors
mask
swagger
logging
postman
scaling
example
Expand Down
103 changes: 103 additions & 0 deletions doc/logging.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
Logging
===============

Flask-RESTPlus extends `Flask's logging <https://flask.palletsprojects.com/en/1.1.x/logging/>`_
by providing each ``API`` and ``Namespace`` it's own standard Python :class:`logging.Logger` instance.
This allows separation of logging on a per namespace basis to allow more fine-grained detail and configuration.

By default, these loggers inherit configuration from the Flask application object logger.

.. code-block:: python
import logging
import flask
from flask_restplus import Api, Resource
# configure root logger
logging.basicConfig(level=logging.INFO)
app = flask.Flask(__name__)
api = Api(app)
# each of these loggers uses configuration from app.logger
ns1 = api.namespace('api/v1', description='test')
ns2 = api.namespace('api/v2', description='test')
@ns1.route('/my-resource')
class MyResource(Resource):
def get(self):
# will log
ns1.logger.info("hello from ns1")
return {"message": "hello"}
@ns2.route('/my-resource')
class MyNewResource(Resource):
def get(self):
# won't log due to INFO log level from app.logger
ns2.logger.debug("hello from ns2")
return {"message": "hello"}
Loggers can be configured individually to override the configuration from the Flask
application object logger. In the above example, ``ns2`` log level can be set to
``DEBUG`` individually:

.. code-block:: python
# ns1 will have log level INFO from app.logger
ns1 = api.namespace('api/v1', description='test')
# ns2 will have log level DEBUG
ns2 = api.namespace('api/v2', description='test')
ns2.logger.setLevel(logging.DEBUG)
@ns1.route('/my-resource')
class MyResource(Resource):
def get(self):
# will log
ns1.logger.info("hello from ns1")
return {"message": "hello"}
@ns2.route('/my-resource')
class MyNewResource(Resource):
def get(self):
# will log
ns2.logger.debug("hello from ns2")
return {"message": "hello"}
Adding additional handlers:


.. code-block:: python
# configure a file handler for ns1 only
ns1 = api.namespace('api/v1')
fh = logging.FileHandler("v1.log")
ns1.logger.addHandler(fh)
ns2 = api.namespace('api/v2')
@ns1.route('/my-resource')
class MyResource(Resource):
def get(self):
# will log to *both* v1.log file and app.logger handlers
ns1.logger.info("hello from ns1")
return {"message": "hello"}
@ns2.route('/my-resource')
class MyNewResource(Resource):
def get(self):
# will log to *only* app.logger handlers
ns2.logger.info("hello from ns2")
return {"message": "hello"}
10 changes: 3 additions & 7 deletions doc/marshalling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ You can use fields to multiplex a single attribute to multiple output values.
This example assumes that bit 1 in the ``flags`` attribute signifies a
"Normal" or "Urgent" item, and bit 2 signifies "Read" or "Unread".
These items might be easy to store in a bitfield,
but for a human readable output it's nice to convert them to seperate string fields.
but for a human readable output it's nice to convert them to separate string fields.

.. code-block:: python
Expand Down Expand Up @@ -168,7 +168,7 @@ To override the default scheme, pass the ``scheme`` keyword argument:
.. code-block:: python
model = {
'uri': fields.Url('todo_resource', absolute=True)
'uri': fields.Url('todo_resource', absolute=True),
'https_uri': fields.Url('todo_resource', absolute=True, scheme='https')
}
Expand Down Expand Up @@ -257,15 +257,11 @@ with other fields, you may want to use an ``OrderedDict`` and use the
:class:`~fields.Wildcard` as the last field ::

>>> from flask_restplus import fields, marshal
>>> from collections import OrderedDict
>>> import json
>>>
>>> wild = fields.Wildcard(fields.Integer)
>>> mod = OrderedDict()
>>> mod['zoro'] = fields.String
>>> mod['*'] = wild
>>> # you can use it in api.model like this:
>>> # some_fields = api.model('MyModel', mod)
>>> # some_fields = api.model('MyModel', {'zoro': fields.String, '*': wild})
>>>
>>> data = {'John': 12, 'bob': 42, 'Jane': '68', 'zoro': 72}
>>> json.dumps(marshal(data, mod))
Expand Down
4 changes: 2 additions & 2 deletions doc/parsing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ The :mod:`~flask_restplus.inputs` module provides some common type handling like

- :func:`~inputs.boolean` for wider boolean handling
- :func:`~inputs.ipv4` and :func:`~inputs.ipv6` for IP adresses
- :func:`~inputs.date_from_iso8601` and :func:`~inputs.datetime_from_iso8601` for ISO8601 date and dateime handling
- :func:`~inputs.date_from_iso8601` and :func:`~inputs.datetime_from_iso8601` for ISO8601 date and datetime handling

You just have to use them as `type` argument:

Expand All @@ -193,7 +193,7 @@ You can also write your own:
raise ValueError('This is not my type')
return parse(value)
# Swagger documntation
# Swagger documentation
my_type.__schema__ = {'type': 'string', 'format': 'my-custom-format'}
Expand Down
2 changes: 0 additions & 2 deletions doc/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,6 @@ you use the ``fields`` module to describe the structure of your response.

.. code-block:: python
from collections import OrderedDict
from flask import Flask
from flask_restplus import fields, Api, Resource
Expand Down
2 changes: 1 addition & 1 deletion doc/scaling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ You don't have to bind url-prefix while declaration of Namespace object.
api.add_namespace(nsX, path='/prefix/of/nsX')
Using this pattern, you simple have to register your API in `app.py` like that:
Using this pattern, you simply have to register your API in `app.py` like that:

.. code-block:: Python
Expand Down
43 changes: 40 additions & 3 deletions doc/swagger.rst
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,7 @@ Models can also be specified with a :class:`~flask_restplus.reqparse.RequestPars
.. note::

Using :class:`~flask_restplus.reqparse.RequestParser` is prefered over the ``api.param()`` decorator
Using :class:`~flask_restplus.reqparse.RequestParser` is preferred over the ``api.param()`` decorator
to document form fields as it also perform validation.

Headers
Expand All @@ -607,7 +607,7 @@ You can document response headers with the ``@api.header()`` decorator shortcut.
def get(self):
pass
If you need to specify an header that appear only on a gvien response,
If you need to specify an header that appear only on a given response,
just use the `@api.response` `headers` parameter.

.. code-block:: python
Expand Down Expand Up @@ -862,7 +862,7 @@ It supports both extensions as `dict` or `kwargs` and perform automatique `x-` p
class Vendor(Resource):
@api.vendor({
'extension-1': {'works': 'with complex values'},
'x-extension-3': 'x- prefix is optionnal',
'x-extension-3': 'x- prefix is optional',
})
def get(self):
return {}
Expand Down Expand Up @@ -953,6 +953,43 @@ You can specify a custom validator URL by setting ``config.SWAGGER_VALIDATOR_URL
api = Api(app)
You can enable [OAuth2 Implicit Flow](https://oauth.net/2/grant-types/implicit/) for retrieving an
authorization token for testing api endpoints interactively within Swagger UI.
The ``config.SWAGGER_UI_OAUTH_CLIENT_ID`` and ``authorizationUrl`` and ``scopes``
will be specific to your OAuth2 IDP configuration.
The realm string is added as a query parameter to authorizationUrl and tokenUrl.
These values are all public knowledge. No *client secret* is specified here.
.. Using PKCE instead of Implicit Flow depends on https://github.com/swagger-api/swagger-ui/issues/5348
.. code-block:: python
from flask import Flask
from flask_restplus import Api
app = Flask(__name__)
app.config.SWAGGER_UI_OAUTH_CLIENT_ID = 'MyClientId'
app.config.SWAGGER_UI_OAUTH_REALM = '-'
app.config.SWAGGER_UI_OAUTH_APP_NAME = 'Demo'
api = Api(
app,
title=app.config.SWAGGER_UI_OAUTH_APP_NAME,
security={'OAuth2': ['read', 'write']},
authorizations={
'OAuth2': {
'type': 'oauth2',
'flow': 'implicit',
'authorizationUrl': 'https://idp.example.com/authorize?audience=https://app.example.com',
'clientId': app.config.SWAGGER_UI_OAUTH_CLIENT_ID,
'scopes': {
'openid': 'Get ID token',
'profile': 'Get identity',
}
}
}
)
You can also specify the initial expansion state with the ``config.SWAGGER_UI_DOC_EXPANSION``
setting (``'none'``, ``'list'`` or ``'full'``):

Expand Down
Loading

0 comments on commit abc4a8d

Please sign in to comment.