A pluggable API specification generator. Currently supports the OpenAPI Specification (f.k.a. the Swagger specification)..

Overview

apispec

PyPI version Build status Documentation marshmallow 3 only OpenAPI Specification 2/3 compatible code style: black

A pluggable API specification generator. Currently supports the OpenAPI Specification (f.k.a. the Swagger specification).

Features

  • Supports the OpenAPI Specification (versions 2 and 3)
  • Framework-agnostic
  • Built-in support for marshmallow
  • Utilities for parsing docstrings

Installation

$ pip install -U apispec

When using marshmallow pluging, ensure a compatible marshmallow version is used:

$ pip install -U apispec[marshmallow]

Example Application

from apispec import APISpec
from apispec.ext.marshmallow import MarshmallowPlugin
from apispec_webframeworks.flask import FlaskPlugin
from flask import Flask
from marshmallow import Schema, fields


# Create an APISpec
spec = APISpec(
    title="Swagger Petstore",
    version="1.0.0",
    openapi_version="3.0.2",
    plugins=[FlaskPlugin(), MarshmallowPlugin()],
)

# Optional marshmallow support
class CategorySchema(Schema):
    id = fields.Int()
    name = fields.Str(required=True)


class PetSchema(Schema):
    category = fields.List(fields.Nested(CategorySchema))
    name = fields.Str()


# Optional security scheme support
api_key_scheme = {"type": "apiKey", "in": "header", "name": "X-API-Key"}
spec.components.security_scheme("ApiKeyAuth", api_key_scheme)


# Optional Flask support
app = Flask(__name__)


@app.route("/random")
def random_pet():
    """A cute furry animal endpoint.
    ---
    get:
      description: Get a random pet
      security:
        - ApiKeyAuth: []
      responses:
        200:
          content:
            application/json:
              schema: PetSchema
    """
    pet = get_random_pet()
    return PetSchema().dump(pet)


# Register the path and the entities within it
with app.test_request_context():
    spec.path(view=random_pet)

Generated OpenAPI Spec

import json

print(json.dumps(spec.to_dict(), indent=2))
# {
#   "paths": {
#     "/random": {
#       "get": {
#         "description": "Get a random pet",
#         "security": [
#           {
#             "ApiKeyAuth": []
#           }
#         ],
#         "responses": {
#           "200": {
#             "content": {
#               "application/json": {
#                 "schema": {
#                   "$ref": "#/components/schemas/Pet"
#                 }
#               }
#             }
#           }
#         }
#       }
#     }
#   },
#   "tags": [],
#   "info": {
#     "title": "Swagger Petstore",
#     "version": "1.0.0"
#   },
#   "openapi": "3.0.2",
#   "components": {
#     "parameters": {},
#     "responses": {},
#     "schemas": {
#       "Category": {
#         "type": "object",
#         "properties": {
#           "name": {
#             "type": "string"
#           },
#           "id": {
#             "type": "integer",
#             "format": "int32"
#           }
#         },
#         "required": [
#           "name"
#         ]
#       },
#       "Pet": {
#         "type": "object",
#         "properties": {
#           "name": {
#             "type": "string"
#           },
#           "category": {
#             "type": "array",
#             "items": {
#               "$ref": "#/components/schemas/Category"
#             }
#           }
#         }
#       }
#       "securitySchemes": {
#          "ApiKeyAuth": {
#            "type": "apiKey",
#            "in": "header",
#            "name": "X-API-Key"
#         }
#       }
#     }
#   }
# }

print(spec.to_yaml())
# components:
#   parameters: {}
#   responses: {}
#   schemas:
#     Category:
#       properties:
#         id: {format: int32, type: integer}
#         name: {type: string}
#       required: [name]
#       type: object
#     Pet:
#       properties:
#         category:
#           items: {$ref: '#/components/schemas/Category'}
#           type: array
#         name: {type: string}
#       type: object
#   securitySchemes:
#     ApiKeyAuth:
#       in: header
#       name: X-API-KEY
#       type: apiKey
# info: {title: Swagger Petstore, version: 1.0.0}
# openapi: 3.0.2
# paths:
#   /random:
#     get:
#       description: Get a random pet
#       responses:
#         200:
#           content:
#             application/json:
#               schema: {$ref: '#/components/schemas/Pet'}
#       security:
#       - ApiKeyAuth: []
# tags: []

Documentation

Documentation is available at https://apispec.readthedocs.io/ .

Ecosystem

A list of apispec-related libraries can be found at the GitHub wiki here:

https://github.com/marshmallow-code/apispec/wiki/Ecosystem

Support apispec

apispec is maintained by a group of volunteers. If you'd like to support the future of the project, please consider contributing to our Open Collective:

Donate to our collective

Professional Support

Professionally-supported apispec is available through the Tidelift Subscription.

Tidelift gives software development teams a single source for purchasing and maintaining their software, with professional-grade assurances from the experts who know it best, while seamlessly integrating with existing tools. [Get professional support]

Get supported apispec with Tidelift

Security Contact Information

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

Project Links

License

MIT licensed. See the bundled LICENSE file for more details.

Comments
  • Nested schema auto resolution as default and respect modifiers in references

    Nested schema auto resolution as default and respect modifiers in references

    Relates to #307

    This is a proof of concept on combining the logic in inspect_schema_for_auto_referencing with the nesting logic in field2property.

    1. Default schema_name_resolver now passed to MarshmallowPlugin
    2. Logic for adding nested schmeas moved from
    3. MarshmallowPlugin.inspect_schema_for_auto_referencing to
    4. OpenAPIConverter.field2property
    5. Removed using LazyDict in favor of regular Dict

    All the tests are passing, but I presume that there are some minor differences in the specs that are not captured by the test. Of potential concern would be cases like this. The second two definition adds would be unnecessary and if the schema name resolved to something other than what the user is putting in as the name there will be extra components in the model. Not sure that is too big of a deal or not.

    At this point the cyclomatic complexity of field2property has increased, but there should be some simplifying that can be done. For example I'm not sure that the unbound self referencing cases are valid and the concept of embedding the reference string in field metadata feels like a relic of not having a ref dictionary.

    backwards incompat 
    opened by Bangertm 30
  • Split out web framework plugins into separate package

    Split out web framework plugins into separate package

    Hi,

    Now that Apispec nears 1.0 release, and given how many issues are open right now I was thinking that maybe web framework plugins should be living in a separate apispec_plugins package. For bw. compatibility existing namespace apispec.ext.$framework could pull them back from separate package.

    This would allow plugin authors to fix bugs in implementations or support newer versions of frameworks without the need to release apispec itself, or even add new plugins.

    I will be attending a hackathon soon and we could probably tackle this.

    opened by ergo 22
  • RFC: Use classes for plugins

    RFC: Use classes for plugins

    I think things would be simpler if plugins were classes.

    I read in the comments that the plugin system is copied on Sphinx. I don't know why Sphinx does it like this, but I don't see the benefit in apispec.

    Since plugins are only referred to by their path as string, there is no direct access to them. So their configuration can be a bit awkward:

    1/ Mutating a global variable in the plugin file.

    2/ Calling a function in the plugin file that will have to store either in a global in the file (which is equivalent to case 1 above) or somewhere else (like map_to_swagger_type stores the mapping in the field's __swagger_field_mapping attribute).

    3/ Acting upon the spec object. This is the case for schema_name_resolver, which is used only in marshmallow plugin, so shouldn't be exposed to spec.

    Likewise, storage is more complicated as it is done in the spec object. The list of schema definitions is stored in spec.plugins['apispec.ext.marshmallow']['refs'] which is the reason why the spec object is passed to all functions in the plugin.

    With plugin classes, the plugin object would keep its storage internal. It wouldn't need globals. It could be configured at instantiation before (or even after, if needed) being passed to the spec object.

    A plugin would just have to define such methods:

    class MyApispecPlugin(BaseApispecPlugin):
        def definition_helper(...):
            [...]
    
        def path_helper(...):
            [...]
    
        def operation_helper(...):
            [...]
    

    Of course, BaseApispecPlugin would provide no-op methods so that child classes would only add needed methods.

    Then, no need to store stuff in the spec object. Variables would be plugin class attributes, modifiable by direct access or plugin object method calls (this is plugin implementation detail). No need to expose plugin internal details to spec (schema_name_resolver). No need to add attributes to the field classes (schema -> swagger type mapping can be stored in a plugin object attribute).

    Here's what setup would look like:

    # Instantiate and configure plugin
    ma_plugin = apispec.ext.marshmallow.MarshmallowPlugin(
        schema_name_resolver = my_func
    )
    
    # Create an APISpec
    spec = APISpec(
        title='Swagger Petstore',
        version='1.0.0',
        plugins=[
            apispec.ext.flask.FlaskPlugin(),  # No specific config to do beforehand
            ma_plugin,  # Configured above
        ],
    )
    

    @sloria, is there a reason I'm missing for the current plugin interface?

    This refactor would solve part of #206.

    feedback welcome backwards incompat 
    opened by lafrech 20
  • Flask extension does not support blueprints

    Flask extension does not support blueprints

    I have organized my views with Flask blueprints, but am unable to document them in the view file, because it is not executed in the application context.

    # app/views/example.py
    
    from flask import Blueprint
    example_view = Blueprint('example_view', __name__)
    
    from app.spec import spec
    
    @bp.route('example', methods=['GET'])
    def get_example():
        """An example.
        ---
        get:
            description: Get an example
            responses:
                200:
                    description: An example
                    schema: ExampleSchema
        """
        return 'example', 200
    
    spec.add_path(view=get_example)
    
      ...
      File "/usr/local/lib/python2.7/site-packages/apispec/core.py", line 170, in add_path
        self, path=path, operations=operations, **kwargs
      File "/usr/local/lib/python2.7/site-packages/apispec/ext/flask.py", line 62, in path_from_view
        rule = _rule_for_view(view)
      File "/usr/local/lib/python2.7/site-packages/apispec/ext/flask.py", line 38, in _rule_for_view
        view_funcs = current_app.view_functions
      File "/usr/local/lib/python2.7/site-packages/werkzeug/local.py", line 343, in __getattr__
        return getattr(self._get_current_object(), name)
      File "/usr/local/lib/python2.7/site-packages/werkzeug/local.py", line 302, in _get_current_object
        return self.__local()
      File "/usr/local/lib/python2.7/site-packages/flask/globals.py", line 34, in _find_app
        raise RuntimeError('working outside of application context')
    RuntimeError: working outside of application context
    

    Is there a way to keep the spec declarations with the blueprint? (It seems like there might not be.)

    Do you think it would be useful to add the ability to add all the views from a blueprint at once?

    I noticed that the flask extension seems to acknowledge that a view could contain multiple paths, but assumes it only contains one. apispec/ext/flask.py#L46

    Maybe something like spec.add_paths() could be added to handle compound view objects?

    ready to claim 
    opened by deckar01 18
  • Support OpenAPI version 3.0

    Support OpenAPI version 3.0

    Hi there,

    We're using APISpec with Marshmallow and aiohttp or sanic and it works really great.

    There are some new great changes with OpenAPI (version 3) vs Swagger API (version 2). Any plan to implement Open API version 3?

    Thanks

    Kind regards,

    Raphaël

    enhancement help wanted 
    opened by rdehouss 16
  • working with webargs meta-location

    working with webargs meta-location

    In my api, in order to isolate validation code, I created a meta-location (following this example from the documentation https://webargs.readthedocs.io/en/latest/advanced.html#meta-locations):

    @parser.location_loader("view_args_and_json")
    def parse_view_args_and_json(request, schema):
        newdata = deepcopy(request.view_args)
        newdata.update(request.json)
        return MultiDictProxy(newdata, schema)
    

    And I'm using it as followed in my api:

    @bp.route("/<attr_id:int>")
    class MyView(MethodView):
        @bp.arguments(PostMySchema, location="view_args_and_json")
        @bp.response(MySchema, code=201)
        def post(self, payload, attr_id):
            my_model = MyModel(**payload)
            db_session.add(my_model)
            db_session.commit()
            return my_model, 201
    

    Here's the schema:

    class MySchema(Schema):
        id = fields.Int(dump_only=True)
        attr_id = fields.Int(load_only=True)
        type = fields.Int()
    
    class PostMySchema(RealtorFilterSchema):
        @validates_schema
        def validate_already_exists(self, data, **kwargs):  # here's the validation bit
            my_model = MyModel.query.filter(
                MyModel.attr_id == data["attr_id"],
                MyModel.type == data["type"],
            ).first()
            if realtor_filter:
                raise ValidationError("Already exists")
    

    And here's the generated openapi.json:

    {
            "parameters": [
              {
                "in": "view_args_and_json",
                "name": "attr_id",
                "required": false,
                "schema": {
                  "type": "integer",
                  "format": "int32"
                }
              },
              {
                "in": "view_args_and_json",
                "name": "type",
                "required": false,
                "schema": {
                  "type": "integer",
                  "format": "int32"
                }
              }
            ]
    }
    

    The swagger interface is unable to post data using this json. My goal is to make openapi understand that view_args_and_json is supposed to be a requestBody and that attr_id is not supposed to be part of the body because it is a load-only field.

    I've tried to add my meta-location to __location_map__ (https://github.com/marshmallow-code/apispec/blob/dev/src/apispec/ext/marshmallow/openapi.py#L30) without success.

    opened by rocambolesque 15
  • Support custom Marshmallow fields

    Support custom Marshmallow fields

    Currently, all custom fields automatically become type="string", format=None due to the hard-coded FIELD_MAPPING. Thus, I cannot extend any marshmallow type, e.g. Dict or Number with apispec support. Currently, the only way to extend apispec support is to patch the FIELD_MAPPING dict.

    opened by frol 15
  • Ignore `load_only` fields if `dump=True` in `fields2jsonschema`?

    Ignore `load_only` fields if `dump=True` in `fields2jsonschema`?

    Hi,

    I'm making use of https://github.com/jmcarp/flask-apispec to automatically generate docs in a personal flask project. This library makes use of your apispec swagger extension to generate docs for requests and responses. I figured out that responses in the generated docs where including marshmallow's load_only fields, which (at least in my case) is not convenient. In the line that I'm linking below you're excluding dump_only fields if dump=False when invoking that method. Do you think it would be a good idea to also ignore load_only fields if dump=True?

    https://github.com/marshmallow-code/apispec/blob/dev/apispec/ext/marshmallow/swagger.py#L492

    I'm opening this for discussion, and I'll be happy to create a PR for that in case you are ok with the proposed functionality.

    help wanted feedback welcome backwards incompat 
    opened by luisincrespo 15
  • explode and style are hardcoded in OpenAPIConverter.property2parameter

    explode and style are hardcoded in OpenAPIConverter.property2parameter

    I've been trying to document webargs's DelimitedList (child class of List) and I'm stuck because I'd need to override hardcoded stuff.

        def field2parameter(self, field, name, default_in):
            location = field.metadata.get("location", None)
            prop = self.field2property(field)
            return self.property2parameter(
                prop,
                name=name,
                required=field.required,
                multiple=isinstance(field, marshmallow.fields.List),   # <--- List
                location=location,
                default_in=default_in,
            )
    
        def property2parameter(self, prop, name, required, multiple, location, default_in):
            openapi_default_in = __location_map__.get(default_in, default_in)
            openapi_location = __location_map__.get(location, openapi_default_in)
            ret = {"in": openapi_location, "name": name}
    
            if openapi_location == "body":
                ret["required"] = False
                ret["name"] = "body"
                ret["schema"] = {"type": "object", "properties": {name: prop}}
                if required:
                    ret["schema"]["required"] = [name]
            else:
                ret["required"] = required
                if self.openapi_version.major < 3:
                    if multiple:
                        ret["collectionFormat"] = "multi"
                    ret.update(prop)
                else:
                    if multiple:                    # <--- when List, set explode and style
                        ret["explode"] = True
                        ret["style"] = "form"
                    if prop.get("description", None):
                        ret["description"] = prop.pop("description")
                    ret["schema"] = prop
            return ret
    

    To document DelimitedList, we'd need to set explode to False. That's assuming we use default , as delimiter. Using space or pipe would require to also modify style.

    To make this more generic, we could remove multiple and create an extensible mechanism to allow custom post-processings after property2parameter. And add a post-processor for List to do what's currently done with multiple.

    Kinda like what's been done with attribute_functions in FieldConverter.

    (Maybe we could separate the property2bodyparameter case as right now it does not involve a specific List case.)

    opened by lafrech 14
  • Can't create servers object using APISpec class

    Can't create servers object using APISpec class

    As per specification, the "servers" object type should be an array/list. This is an example:

    servers:
    - url: https://localhost
    

    To translate this in apispec, I should add the following parameter to the class:

    servers=[{
        "url": "https://localhost"
    }]
    

    However, the class APISpec only allows objects of type dictionary for **options. In any IDE this results in a warning about wrong type. I solved the issue modifying line 184 of core.py in this way:

    :param dict|list options: Optional top-level keys
    
    question 
    opened by dariofaccin 13
  • InvalidParameterError exception

    InvalidParameterError exception

    Hi,

    On apispec>2.0.0 I'm getting:

    apispec.exceptions.InvalidParameterError: Missing keys ['name', 'in'] for parameter
    

    I may be mistaken but it seems that I do have name and in on all parameters Once more I'm sorry for the long JSON spec:

    {
      "components": {
        "parameters": {
          "get_info_schema": {
            "in": "query",
            "name": "q",
            "schema": {
              "properties": {
                "add_columns": {
                  "additionalProperties": {
                    "properties": {
                      "page": {
                        "type": "integer"
                      },
                      "page_size": {
                        "type": "integer"
                      }
                    },
                    "type": "object"
                  },
                  "type": "object"
                },
                "keys": {
                  "items": {
                    "enum": [
                      "add_columns",
                      "edit_columns",
                      "filters",
                      "permissions",
                      "add_title",
                      "edit_title",
                      "none"
                    ],
                    "type": "string"
                  },
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          "get_item_schema": {
            "in": "query",
            "name": "q",
            "schema": {
              "properties": {
                "columns": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "keys": {
                  "items": {
                    "enum": [
                      "show_columns",
                      "description_columns",
                      "label_columns",
                      "show_title",
                      "none"
                    ],
                    "type": "string"
                  },
                  "type": "array"
                }
              },
              "type": "object"
            }
          },
          "get_list_schema": {
            "in": "query",
            "name": "q",
            "schema": {
              "properties": {
                "columns": {
                  "items": {
                    "type": "string"
                  },
                  "type": "array"
                },
                "filters": {
                  "items": {
                    "properties": {
                      "col": {
                        "type": "string"
                      },
                      "opr": {
                        "type": "string"
                      },
                      "value": {
                        "anyOf": [
                          {
                            "type": "number"
                          },
                          {
                            "type": "string"
                          },
                          {
                            "type": "boolean"
                          }
                        ]
                      }
                    },
                    "type": "object"
                  },
                  "type": "array"
                },
                "keys": {
                  "items": {
                    "enum": [
                      "list_columns",
                      "order_columns",
                      "label_columns",
                      "description_columns",
                      "list_title",
                      "none"
                    ],
                    "type": "string"
                  },
                  "type": "array"
                },
                "order_column": {
                  "type": "string"
                },
                "order_direction": {
                  "enum": [
                    "asc",
                    "desc"
                  ],
                  "type": "string"
                },
                "page": {
                  "type": "integer"
                },
                "page_size": {
                  "type": "integer"
                }
              },
              "type": "object"
            }
          }
        },
        "responses": {
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Bad request"
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Unauthorized"
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Not found"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Could not process entity"
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "type": "object"
                }
              }
            },
            "description": "Fatal error"
          }
        },
        "schemas": {
          "GroupModelApi.get": {
            "properties": {
              "name": {
                "maxLength": 50,
                "type": "string"
              }
            },
            "required": [
              "name"
            ],
            "type": "object"
          },
          "GroupModelApi.get_list": {
            "properties": {
              "name": {
                "maxLength": 50,
                "type": "string"
              }
            },
            "required": [
              "name"
            ],
            "type": "object"
          },
          "GroupModelApi.post": {
            "properties": {
              "name": {
                "maxLength": 50,
                "type": "string"
              }
            },
            "required": [
              "name"
            ],
            "type": "object"
          },
          "GroupModelApi.put": {
            "properties": {
              "name": {
                "maxLength": 50,
                "type": "string"
              }
            },
            "required": [
              "name"
            ],
            "type": "object"
          },
          "get_info_schema": {
            "properties": {
              "add_columns": {
                "additionalProperties": {
                  "properties": {
                    "page": {
                      "type": "integer"
                    },
                    "page_size": {
                      "type": "integer"
                    }
                  },
                  "type": "object"
                },
                "type": "object"
              },
              "keys": {
                "items": {
                  "enum": [
                    "add_columns",
                    "edit_columns",
                    "filters",
                    "permissions",
                    "add_title",
                    "edit_title",
                    "none"
                  ],
                  "type": "string"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "get_item_schema": {
            "properties": {
              "columns": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "keys": {
                "items": {
                  "enum": [
                    "show_columns",
                    "description_columns",
                    "label_columns",
                    "show_title",
                    "none"
                  ],
                  "type": "string"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "get_list_schema": {
            "properties": {
              "columns": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "filters": {
                "items": {
                  "properties": {
                    "col": {
                      "type": "string"
                    },
                    "opr": {
                      "type": "string"
                    },
                    "value": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "string"
                        },
                        {
                          "type": "boolean"
                        }
                      ]
                    }
                  },
                  "type": "object"
                },
                "type": "array"
              },
              "keys": {
                "items": {
                  "enum": [
                    "list_columns",
                    "order_columns",
                    "label_columns",
                    "description_columns",
                    "list_title",
                    "none"
                  ],
                  "type": "string"
                },
                "type": "array"
              },
              "order_column": {
                "type": "string"
              },
              "order_direction": {
                "enum": [
                  "asc",
                  "desc"
                ],
                "type": "string"
              },
              "page": {
                "type": "integer"
              },
              "page_size": {
                "type": "integer"
              }
            },
            "type": "object"
          }
        },
        "securitySchemes": {
          "jwt": {
            "bearerFormat": "JWT",
            "scheme": "bearer",
            "type": "http"
          },
          "jwt_refresh": {
            "bearerFormat": "JWT",
            "scheme": "bearer",
            "type": "http"
          }
        }
      },
      "info": {
        "description": "F.A.B. Example",
        "title": "F.A.B. Example",
        "version": "v1"
      },
      "openapi": "3.0.2",
      "paths": {
        "/group/": {
          "get": {
            "parameters": [
              {
                "in": "query",
                "name": "q",
                "schema": {
                  "properties": {
                    "columns": {
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "filters": {
                      "items": {
                        "properties": {
                          "col": {
                            "type": "string"
                          },
                          "opr": {
                            "type": "string"
                          },
                          "value": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "string"
                              },
                              {
                                "type": "boolean"
                              }
                            ]
                          }
                        },
                        "type": "object"
                      },
                      "type": "array"
                    },
                    "keys": {
                      "items": {
                        "enum": [
                          "list_columns",
                          "order_columns",
                          "label_columns",
                          "description_columns",
                          "list_title",
                          "none"
                        ],
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "order_column": {
                      "type": "string"
                    },
                    "order_direction": {
                      "enum": [
                        "asc",
                        "desc"
                      ],
                      "type": "string"
                    },
                    "page": {
                      "type": "integer"
                    },
                    "page_size": {
                      "type": "integer"
                    }
                  },
                  "type": "object"
                }
              }
            ],
            "responses": {
              "200": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "description_columns": {
                          "type": "object"
                        },
                        "ids": {
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "label_columns": {
                          "type": "object"
                        },
                        "list_columns": {
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "list_title": {
                          "type": "string"
                        },
                        "order_columns": {
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "result": {
                          "items": {
                            "properties": {
                              "name": {
                                "maxLength": 50,
                                "type": "string"
                              }
                            },
                            "required": [
                              "name"
                            ],
                            "type": "object"
                          },
                          "type": "array"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Items from Model"
              },
              "400": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Bad request"
              },
              "401": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Unauthorized"
              },
              "422": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Could not process entity"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "security": [
              {
                "jwt": []
              }
            ],
            "tags": [
              "GroupModelApi"
            ]
          },
          "post": {
            "requestBody": {
              "content": {
                "application/json": {
                  "schema": {
                    "properties": {
                      "name": {
                        "maxLength": 50,
                        "type": "string"
                      }
                    },
                    "required": [
                      "name"
                    ],
                    "type": "object"
                  }
                }
              },
              "description": "Model schema",
              "required": true
            },
            "responses": {
              "201": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "result": {
                          "properties": {
                            "name": {
                              "maxLength": 50,
                              "type": "string"
                            }
                          },
                          "required": [
                            "name"
                          ],
                          "type": "object"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Item inserted"
              },
              "400": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Bad request"
              },
              "401": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Unauthorized"
              },
              "422": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Could not process entity"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "security": [
              {
                "jwt": []
              }
            ],
            "tags": [
              "GroupModelApi"
            ]
          }
        },
        "/group/_info": {
          "get": {
            "parameters": [
              {
                "in": "query",
                "name": "q",
                "schema": {
                  "properties": {
                    "add_columns": {
                      "additionalProperties": {
                        "properties": {
                          "page": {
                            "type": "integer"
                          },
                          "page_size": {
                            "type": "integer"
                          }
                        },
                        "type": "object"
                      },
                      "type": "object"
                    },
                    "keys": {
                      "items": {
                        "enum": [
                          "add_columns",
                          "edit_columns",
                          "filters",
                          "permissions",
                          "add_title",
                          "edit_title",
                          "none"
                        ],
                        "type": "string"
                      },
                      "type": "array"
                    }
                  },
                  "type": "object"
                }
              }
            ],
            "responses": {
              "200": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "add_columns": {
                          "type": "object"
                        },
                        "edit_columns": {
                          "type": "object"
                        },
                        "filters": {
                          "type": "object"
                        },
                        "permissions": {
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Item from Model"
              },
              "400": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Bad request"
              },
              "401": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Unauthorized"
              },
              "422": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Could not process entity"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "security": [
              {
                "jwt": []
              }
            ],
            "tags": [
              "GroupModelApi"
            ]
          }
        },
        "/group/{pk}": {
          "delete": {
            "parameters": [
              {
                "in": "path",
                "name": "pk",
                "required": true,
                "schema": {
                  "type": "integer"
                }
              }
            ],
            "responses": {
              "200": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Item deleted"
              },
              "404": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Not found"
              },
              "422": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Could not process entity"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "security": [
              {
                "jwt": []
              }
            ],
            "tags": [
              "GroupModelApi"
            ]
          },
          "get": {
            "parameters": [
              {
                "in": "path",
                "name": "pk",
                "required": true,
                "schema": {
                  "type": "integer"
                }
              },
              {
                "in": "query",
                "name": "q",
                "schema": {
                  "properties": {
                    "columns": {
                      "items": {
                        "type": "string"
                      },
                      "type": "array"
                    },
                    "keys": {
                      "items": {
                        "enum": [
                          "show_columns",
                          "description_columns",
                          "label_columns",
                          "show_title",
                          "none"
                        ],
                        "type": "string"
                      },
                      "type": "array"
                    }
                  },
                  "type": "object"
                }
              }
            ],
            "responses": {
              "200": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "description_columns": {
                          "type": "object"
                        },
                        "id": {
                          "type": "string"
                        },
                        "label_columns": {
                          "type": "object"
                        },
                        "result": {
                          "properties": {
                            "name": {
                              "maxLength": 50,
                              "type": "string"
                            }
                          },
                          "required": [
                            "name"
                          ],
                          "type": "object"
                        },
                        "show_columns": {
                          "items": {
                            "type": "string"
                          },
                          "type": "array"
                        },
                        "show_title": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Item from Model"
              },
              "400": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Bad request"
              },
              "401": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Unauthorized"
              },
              "404": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Not found"
              },
              "422": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Could not process entity"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "security": [
              {
                "jwt": []
              }
            ],
            "tags": [
              "GroupModelApi"
            ]
          },
          "put": {
            "parameters": [
              {
                "in": "path",
                "name": "pk",
                "required": true,
                "schema": {
                  "type": "integer"
                }
              }
            ],
            "requestBody": {
              "content": {
                "application/json": {
                  "schema": {
                    "properties": {
                      "name": {
                        "maxLength": 50,
                        "type": "string"
                      }
                    },
                    "required": [
                      "name"
                    ],
                    "type": "object"
                  }
                }
              },
              "description": "Model schema",
              "required": true
            },
            "responses": {
              "200": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "result": {
                          "properties": {
                            "name": {
                              "maxLength": 50,
                              "type": "string"
                            }
                          },
                          "required": [
                            "name"
                          ],
                          "type": "object"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Item changed"
              },
              "400": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Bad request"
              },
              "401": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Unauthorized"
              },
              "404": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Not found"
              },
              "422": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Could not process entity"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "security": [
              {
                "jwt": []
              }
            ],
            "tags": [
              "GroupModelApi"
            ]
          }
        },
        "/openapi/{version}/_openapi": {
          "get": {
            "parameters": [
              {
                "in": "path",
                "name": "version",
                "required": true,
                "schema": {
                  "type": "string"
                }
              }
            ],
            "responses": {
              "200": {
                "content": {
                  "application/json": {
                    "schema": {
                      "type": "object"
                    }
                  }
                },
                "description": "Item from Model"
              },
              "404": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Not found"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "security": [
              {
                "jwt": []
              }
            ],
            "tags": [
              "OpenApi"
            ]
          }
        },
        "/security/login": {
          "post": {
            "requestBody": {
              "content": {
                "application/json": {
                  "schema": {
                    "properties": {
                      "password": {
                        "type": "string"
                      },
                      "provider": {
                        "enum": [
                          "db",
                          "ldap"
                        ],
                        "type": "string"
                      },
                      "refresh": {
                        "type": "boolean"
                      },
                      "username": {
                        "type": "string"
                      }
                    },
                    "type": "object"
                  }
                }
              },
              "required": true
            },
            "responses": {
              "200": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "access_token": {
                          "type": "string"
                        },
                        "refresh_token": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Authentication Successful"
              },
              "400": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Bad request"
              },
              "401": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Unauthorized"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "tags": [
              "SecurityApi"
            ]
          }
        },
        "/security/refresh": {
          "post": {
            "responses": {
              "200": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "refresh_token": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Refresh Successful"
              },
              "401": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Unauthorized"
              },
              "500": {
                "content": {
                  "application/json": {
                    "schema": {
                      "properties": {
                        "message": {
                          "type": "string"
                        }
                      },
                      "type": "object"
                    }
                  }
                },
                "description": "Fatal error"
              }
            },
            "security": [
              {
                "jwt_refresh": []
              }
            ],
            "tags": [
              "SecurityApi"
            ]
          }
        }
      },
      "servers": [
        {
          "url": "/api/v1"
        }
      ]
    }
    
    opened by dpgaspar 13
  • Datetime support for multiple format

    Datetime support for multiple format

    Adding a function datetime2properties to support the differents formats of marshamllow.field.DateTime. An exemple for custom DateTime format has been added to the doc in Using Plugins / Marshmallow Plugin

    The support for timestamp and timestamp_ms mean that DateTime type can be either "string" or "integer". Format can also have multiple values. Because of that 2 test where modified to account for that variability:

    • test_field2property_type
    • test_field2property_formats

    Then 6 tests were added to test the different output of datetime2properties.

    opened by TheBigRoomXXL 0
  • Marshmallow plugin doesn't document the format of fields.DateTime() correctly

    Marshmallow plugin doesn't document the format of fields.DateTime() correctly

    Marshmallow support multiple format for DateTime:

    format: Either "rfc" (for RFC822), "iso" (for ISO8601), "timestamp", "timestamp_ms" (for a POSIX timestamp) or a date format string. If None, defaults to “iso”.

    I was expecting apispec to adapt documentation base on the format but apispec always default to iso format. To change this behavior , I guess the FieldConverterMixin.field2type_and_format would need to be changed but I don't know exactly how.

    I don't know if that qualify as a "bug" but it would certainly be nice to have that in the future.

    bug 
    opened by TheBigRoomXXL 2
  • Issue with nested self-referencing schemas

    Issue with nested self-referencing schemas

    I have an issue with nested self-referencing schema,

    class GroupSchema(HasPermissionMixin, ModelSchema):
        content = fields.Nested(GroupParamSchema, required=True)
    
    class GroupParamSchema(Schema):
        filters = fields.Nested(FilterSchema, required=True, many=True)
    
    class FilterSchema(Schema):
        next_filter = fields.Nested("FilterSchema", required=False, allow_none=True)
    

    The issue is with FilterSchema

    I have a helper method that converts Marshmallow Schema to an OpenApiJson object:

    def get_openapi_schema(
        serializer,
    ):
        spec = APISpec(
            title="",
            version="",
            openapi_version="3.0.2",
            plugins=[MarshmallowPlugin(schema_name_resolver=schema_name_resolver)],
        )
    
        openapi_schema = OpenAPIConverter(openapi_version="3.0.2",schema_name_resolver=schema_name_resolver,spec=spec)
        return {200: openapi_schema.schema2jsonschema(serializer)}
    

    The schema_name_resolver as described in the docs should not return None for Circular schemas

    def schema_name_resolver(schema):
    
        schema_name = resolve_schema_cls(schema).__name__
        circular = False
        values = list(schema.fields.values())
    
        for value in values:
            if value.__class__.__name__ == "Nested":
                if value.nested == schema_name:
                    circular = True
                    break
    
        if circular:
            return schema_name
    
        return None
    

    But it still complains:

     File "/usr/local/lib/python3.9/site-packages/apispec/ext/marshmallow/openapi.py", line 297, in get_ref_dict
        ref_schema = self.spec.components.get_ref("schema", self.refs[schema_key])
    KeyError: (<class 'veylinx.api.insights.serializers.base.FilterSchema'>, None, frozenset(), frozenset(), frozenset(), False)
    

    And I'm sure that the schema_name_resolver is returning a string when the schema is circular

    Using a resolver as lambda schema_class: None will raise the error below which is understandable!

    apispec.exceptions.APISpecError: Name resolver returned None for schema <FilterSchema(many=False)> which is part of a chain of circular referencing schemas. Please ensure that the schema_name_resolver passed to MarshmallowPlugin returns a string for all circular referencing schemas.
    

    I'm using:

    Django==4.0.8
    apispec==6.0.2
    marshmallow==3.19.0
    Debian GNU/Linux 11 (bullseye)
    
    question 
    opened by mouadennasri 2
  • Incorrect handling of nullable enums in marshmallow converter

    Incorrect handling of nullable enums in marshmallow converter

    According to the OpenAPI specification, nullable enums must list null in the allowed options. apispec doesn't do this by default, so in my projects I've had to patch this behaviour in with the following attribute function:

    def field_to_properties(self, field, ret):
        enum = ret.get('enum', [])
        nullable = ret.get('nullable', False)
        if enum and nullable and None not in enum:
            return {'enum': [*enum, None]}
        return {}
    

    It would be nice if apispec implemented this.

    opened by pmdarrow 1
  • Add support for marshmallow.fields.Number.as_string

    Add support for marshmallow.fields.Number.as_string

    Some applications serialize decimal numbers as strings, as binary representation of floats can't be precise. However, when the OpenAPI documentation is created, this is currently not being taken into account if the Decimal type is used with the as_string option. With this change the documentation accurately represents what is being returned.

    opened by rockTA 1
  • Multiple schemas for same nested type in data class with marshmallow-dataclass > 8.5.3

    Multiple schemas for same nested type in data class with marshmallow-dataclass > 8.5.3

    When generating a schema for a single data class referencing same nested type in multiple fields each field get a separate schema. Even though it is the same type. Though, the trick is that this only happens if you first get the schema for the type in a different call context.

    Code to reproduce the bug:

    from dataclasses import dataclass
    
    import marshmallow_dataclass
    from apispec import APISpec
    from apispec.ext.marshmallow import MarshmallowPlugin
    
    
    @dataclass
    class Foo:
        s: str
    
    @dataclass
    class Bar:
        a: Foo
        b: Foo
    
    
    def get_marshmallow_schema():
        marshmallow_dataclass.class_schema(Bar)()
    
    # When this function is called the bug is triggered. Commenting out this line makes the bug not happen.
    get_marshmallow_schema()
    
    
    spec = APISpec(
        title="Test schema",
        version="0.0.1",
        openapi_version="3.0.3",
        plugins=[MarshmallowPlugin()],
    )
    
    spec.components.schema("bar", schema=marshmallow_dataclass.class_schema(Bar))
    
    print(spec.to_yaml())
    

    Running the above code will output the warning from marshmallow plugin: UserWarning: Multiple schemas resolved to the name Foo. The name has been modified. Either manually add each of the schemas with a different name or provide a custom schema_name_resolver.

    And the schema for Bar will look like:

    properties:
            a:
              $ref: '#/components/schemas/Foo1'
            b:
              $ref: '#/components/schemas/Foo'
          required:
          - a
          - b
          type: object
    
    opened by DanielPettersson 1
Owner
marshmallow-code
Python object serialization and deserialization, lightweight and fluffy
marshmallow-code
Automated generation of real Swagger/OpenAPI 2.0 schemas from Django REST Framework code.

drf-yasg - Yet another Swagger generator Generate real Swagger/OpenAPI 2.0 specifications from a Django Rest Framework API. Compatible with Django Res

Cristi Vîjdea 3k Dec 31, 2022
API spec validator and OpenAPI document generator for Python web frameworks.

API spec validator and OpenAPI document generator for Python web frameworks.

1001001 249 Dec 22, 2022
Swagger Documentation Generator for Django REST Framework: deprecated

Django REST Swagger: deprecated (2019-06-04) This project is no longer being maintained. Please consider drf-yasg as an alternative/successor. I haven

Marc Gibbons 2.6k Jan 3, 2023
A swagger tool for tornado, using python to write api doc!

SwaggerDoc About A swagger tool for tornado, using python to write api doc! Installation pip install swagger-doc Quick Start code import tornado.ioloo

aaashuai 1 Jan 10, 2022
Flask-Rebar combines flask, marshmallow, and swagger for robust REST services.

Flask-Rebar Flask-Rebar combines flask, marshmallow, and swagger for robust REST services. Features Request and Response Validation - Flask-Rebar reli

PlanGrid 223 Dec 19, 2022
SCTYMN is a GitHub repository that includes some simple scripts(currently only python scripts) that can be useful.

Simple Codes That You Might Need SCTYMN is a GitHub repository that includes some simple scripts(currently only python scripts) that can be useful. In

CodeWriter21 2 Jan 21, 2022
Sane and flexible OpenAPI 3 schema generation for Django REST framework.

drf-spectacular Sane and flexible OpenAPI 3.0 schema generation for Django REST framework. This project has 3 goals: Extract as much schema informatio

T. Franzel 1.4k Jan 8, 2023
Test utility for validating OpenAPI documentation

DRF OpenAPI Tester This is a test utility to validate DRF Test Responses against OpenAPI 2 and 3 schema. It has built-in support for: OpenAPI 2/3 yaml

snok 106 Jan 5, 2023
A curated list of awesome tools for Sphinx Python Documentation Generator

Awesome Sphinx (Python Documentation Generator) A curated list of awesome extra libraries, software and resources for Sphinx (Python Documentation Gen

Hyunjun Kim 831 Dec 27, 2022
Literate-style documentation generator.

888888b. 888 Y88b 888 888 888 d88P 888 888 .d8888b .d8888b .d88b. 8888888P" 888 888 d88P" d88P" d88""88b 888 888 888

Pycco 808 Dec 27, 2022
Documentation generator for C++ based on Doxygen and mosra/m.css.

mosra/m.css is a Doxygen-based documentation generator that significantly improves on Doxygen's default output by controlling some of Doxygen's more unruly options, supplying it's own slick HTML+CSS generation and adding a fantastic live search feature.

Mark Gillard 109 Dec 7, 2022
Dynamic Resume Generator

Dynamic Resume Generator

Quinten Lisowe 15 May 19, 2022
🍭 epub generator for lightnovel.us 轻之国度 epub 生成器

lightnovel_epub 本工具用于基于轻之国度网页生成epub小说。 注意:本工具仅作学习交流使用,作者不对内容和使用情况付任何责任! 原理 直接抓取 HTML,然后将其中的图片下载至本地,随后打包成 EPUB。

gyro永不抽风 188 Dec 30, 2022
Markdown documentation generator from Google docstrings

mkgendocs A Python package for automatically generating documentation pages in markdown for Python source files by parsing Google style docstring. The

Davide Nunes 44 Dec 18, 2022
Word document generator with python

In this study, real world data is anonymized. The content is completely different, but the structure is the same. It was a script I prepared for the backend of a work using UiPath.

Ezgi Turalı 3 Jan 30, 2022
API Documentation for Python Projects

API Documentation for Python Projects. Example pdoc -o ./html pdoc generates this website: pdoc.dev/docs. Installation pip install pdoc pdoc is compat

mitmproxy 1.4k Jan 7, 2023
Create docsets for Dash.app-compatible API browser.

doc2dash: Create Docsets for Dash.app and Clones doc2dash is an MIT-licensed extensible Documentation Set generator intended to be used with the Dash.

Hynek Schlawack 498 Dec 30, 2022
📖 Generate markdown API documentation from Google-style Python docstring. The lazy alternative to Sphinx.

lazydocs Generate markdown API documentation for Google-style Python docstring. Getting Started • Features • Documentation • Support • Contribution •

Machine Learning Tooling 118 Dec 31, 2022
Automated Integration Testing and Live Documentation for your API

Automated Integration Testing and Live Documentation for your API

ScanAPI 1.3k Dec 30, 2022