diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 0a24f1f4..960399ad 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.4.0 +current_version = 3.0.0 commit = True tag = True diff --git a/.flake8 b/.flake8 index 8f362bcd..b1a9065f 100644 --- a/.flake8 +++ b/.flake8 @@ -3,3 +3,4 @@ max-line-length = 120 exclude = .git/*, build/*, examples/*, venv/*, setup.py per-file-ignores = flask_rebar/__init__.py: F401 flask_rebar/*/__init__.py: F401 +extend-ignore = E501 diff --git a/README.rst b/README.rst index c9b415fd..f47fd295 100644 --- a/README.rst +++ b/README.rst @@ -111,6 +111,15 @@ Installation pip install flask-rebar +Replacing static swagger-ui files +------------- + +If you'd like to replace swagger-ui's static files (`flask_rebar/swagger_ui/static`) with those of the latest release, +run the following from the root of the project. + +.. code-block:: + curl -L https://api.github.com/repos/swagger-api/swagger-ui/tarball | tar -xv --directory=flask_rebar/swagger_ui/static --strip-components=2 "*/dist/" + Documentation ------------- diff --git a/flask_rebar/swagger_generation/authenticator_to_swagger.py b/flask_rebar/swagger_generation/authenticator_to_swagger.py index 5339ca1f..63d3060f 100644 --- a/flask_rebar/swagger_generation/authenticator_to_swagger.py +++ b/flask_rebar/swagger_generation/authenticator_to_swagger.py @@ -43,12 +43,12 @@ def get_security_schemes(self, obj, context): OpenAPI Specification for defining security schemes 2.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-definitions-object - 3.0.2: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#fixed-fields-6 + 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#fixed-fields-6 (see securitySchemes field) OpenAPI Specification for Security Scheme Object 2.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-scheme-object - 3.0.2: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#security-scheme-object + 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#security-scheme-object Example: An authenticator that makes use of an api_key and an application_key scheme @@ -81,7 +81,7 @@ def get_security_requirements(self, obj, context): OpenAPI Specification for Security Requirement Object 2.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#security-requirement-object - 3.0.2: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#security-requirement-object + 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#security-requirement-object Example: Require oauth with scope "read:stuff" OR api_key AND application_key [ diff --git a/flask_rebar/swagger_generation/marshmallow_to_swagger.py b/flask_rebar/swagger_generation/marshmallow_to_swagger.py index 892f9e06..635469db 100644 --- a/flask_rebar/swagger_generation/marshmallow_to_swagger.py +++ b/flask_rebar/swagger_generation/marshmallow_to_swagger.py @@ -295,11 +295,16 @@ def convert(self, obj, context): ) ) - if context.openapi_version == 3 and obj.allow_none: - jsonschema_obj["nullable"] = True - return jsonschema_obj + # With OpenApi 3.1 nullable has been removed entirely + # and allowing 'none' means we return an array of allowed types that includes sw.null + def null_type_determination(self, obj, context, sw_type): + if context.openapi_version == 3 and obj.allow_none: + return [sw_type, sw.null] + else: + return sw_type + @sets_swagger_attr(sw.default) def get_default(self, obj, context): if ( @@ -349,7 +354,7 @@ class ListConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.array + return self.null_type_determination(obj, context, sw.array) @sets_swagger_attr(sw.items) def get_items(self, obj, context): @@ -361,7 +366,7 @@ class DictConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.object_ + return self.null_type_determination(obj, context, sw.object_) class IntegerConverter(FieldConverter): @@ -369,7 +374,7 @@ class IntegerConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.integer + return self.null_type_determination(obj, context, sw.integer) class StringConverter(FieldConverter): @@ -377,7 +382,7 @@ class StringConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.string + return self.null_type_determination(obj, context, sw.string) class NumberConverter(FieldConverter): @@ -385,7 +390,7 @@ class NumberConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.number + return self.null_type_determination(obj, context, sw.number) class BooleanConverter(FieldConverter): @@ -393,7 +398,7 @@ class BooleanConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.boolean + return self.null_type_determination(obj, context, sw.boolean) class DateTimeConverter(FieldConverter): @@ -401,7 +406,7 @@ class DateTimeConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.string + return self.null_type_determination(obj, context, sw.string) @sets_swagger_attr(sw.format_) def get_format(self, obj, context): @@ -413,7 +418,7 @@ class UUIDConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.string + return self.null_type_determination(obj, context, sw.string) @sets_swagger_attr(sw.format_) def get_format(self, obj, context): @@ -425,7 +430,7 @@ class DateConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): - return sw.string + return self.null_type_determination(obj, context, sw.string) @sets_swagger_attr(sw.format_) def get_format(self, obj, context): @@ -438,7 +443,9 @@ class MethodConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): if "swagger_type" in obj.metadata: - return obj.metadata["swagger_type"] + return self.null_type_determination( + obj, context, obj.metadata["swagger_type"] + ) else: raise ValueError( 'Must include "swagger_type" ' "keyword argument in Method field" @@ -451,7 +458,9 @@ class FunctionConverter(FieldConverter): @sets_swagger_attr(sw.type_) def get_type(self, obj, context): if "swagger_type" in obj.metadata: - return obj.metadata["swagger_type"] + return self.null_type_determination( + obj, context, obj.metadata["swagger_type"] + ) else: raise ValueError( 'Must include "swagger_type" ' "keyword argument in Function field" @@ -653,13 +662,13 @@ def get_type(self, obj, context): # I'm going out on a limb and assuming your enum uses same type for all vals, else caveat emptor: value_type = type(next(iter(obj.enum)).value) if value_type is int: - return sw.integer + return self.null_type_determination(obj, context, sw.integer) elif value_type is float: - return sw.number + return self.null_type_determination(obj, context, sw.number) else: - return sw.string + return self.null_type_determination(obj, context, sw.string) else: - return sw.string + return self.null_type_determination(obj, context, sw.string) @sets_swagger_attr(sw.enum) def get_enum(self, obj, context): diff --git a/flask_rebar/swagger_generation/swagger_generator_v3.py b/flask_rebar/swagger_generation/swagger_generator_v3.py index a4db6510..8bc544a0 100644 --- a/flask_rebar/swagger_generation/swagger_generator_v3.py +++ b/flask_rebar/swagger_generation/swagger_generator_v3.py @@ -30,7 +30,7 @@ class SwaggerV3Generator(SwaggerGenerator): - """Generates a v3.0.2 Swagger specification from a Rebar object. + """Generates a v3.1.0 Swagger specification from a Rebar object. Not all things are retrievable from the Rebar object, so this guy also needs some additional information to complete the job. @@ -49,7 +49,7 @@ class SwaggerV3Generator(SwaggerGenerator): A list of Server Objects to set as the server metadata for the specification. """ - _open_api_version = "3.0.2" + _open_api_version = "3.1.0" def __init__( self, diff --git a/flask_rebar/swagger_ui/static/favicon-16x16.png b/flask_rebar/swagger_ui/static/favicon-16x16.png index 0f7e13b0..8b194e61 100644 Binary files a/flask_rebar/swagger_ui/static/favicon-16x16.png and b/flask_rebar/swagger_ui/static/favicon-16x16.png differ diff --git a/flask_rebar/swagger_ui/static/favicon-32x32.png b/flask_rebar/swagger_ui/static/favicon-32x32.png index b0a3352f..249737fe 100644 Binary files a/flask_rebar/swagger_ui/static/favicon-32x32.png and b/flask_rebar/swagger_ui/static/favicon-32x32.png differ diff --git a/flask_rebar/swagger_ui/static/index.css b/flask_rebar/swagger_ui/static/index.css new file mode 100644 index 00000000..f2376fda --- /dev/null +++ b/flask_rebar/swagger_ui/static/index.css @@ -0,0 +1,16 @@ +html { + box-sizing: border-box; + overflow: -moz-scrollbars-vertical; + overflow-y: scroll; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +body { + margin: 0; + background: #fafafa; +} diff --git a/flask_rebar/swagger_ui/static/index.html b/flask_rebar/swagger_ui/static/index.html new file mode 100644 index 00000000..84ae62d3 --- /dev/null +++ b/flask_rebar/swagger_ui/static/index.html @@ -0,0 +1,19 @@ + + + +
+ +