Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot generate Markdown file from valid API definition in YAML #34

Open
volphy opened this issue Aug 7, 2023 · 2 comments
Open

Cannot generate Markdown file from valid API definition in YAML #34

volphy opened this issue Aug 7, 2023 · 2 comments

Comments

@volphy
Copy link

volphy commented Aug 7, 2023

I cannot generate Markdown file from properly validated API definition file:

$ oad --verbose gen-docs -s docs/api/swagger.yaml -d api.md
[08/07/23 12:35:24] DEBUG    Running in --verbose mode                                                                                                                                                   main.py:27
                    DEBUG    Reading from file docs/api/swagger.yaml                                                                                                                                   source.py:77
Traceback (most recent call last):
  File "<redacted_path>/.venv/bin/oad", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
         ^^^^^^^^^^^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/click/core.py", line 1688, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/openapidocs/commands/docs.py", line 51, in generate_documents_command
    generate_document(source, destination, style)
  File "<redacted_path>/.venv/lib/python3.11/site-packages/openapidocs/mk/generate.py", line 14, in generate_document
    html = handler.write()
           ^^^^^^^^^^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/openapidocs/mk/v3/__init__.py", line 427, in write
    operations=self.get_operations(),
               ^^^^^^^^^^^^^^^^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/openapidocs/mk/v3/__init__.py", line 181, in get_operations
    tag = self.get_tag(path_item) or ""
          ^^^^^^^^^^^^^^^^^^^^^^^
  File "<redacted_path>/.venv/lib/python3.11/site-packages/openapidocs/mk/v3/__init__.py", line 219, in get_tag
    tags = operation.get("tags")
           ^^^^^^^^^^^^^
AttributeError: 'str' object has no attribute 'get'

API definition file swagger.yaml (validated with https://github.com/OpenAPITools/openapi-generator):

openapi: 3.0.3
info:
  title: My API
  description: My API
  version: 1.0.0
servers:
  - url: 'http://localhost:8080/'

paths:
  /client:
    description: Client onboarding operations

    post:
      description: Onboard a new client
      responses:
        201:
          description: Client onboarded successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OnboardedClientDetails'
        400:
          description: Missing attribute in the payload
        403:
          description: Not authorized
        422:
          description: Payload formatted incorrectly
        500:
          description: Internal server error
      requestBody:
        description: Payload to be sent
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OnboardClientRequest'
      x-amazon-apigateway-integration:
        type: "aws_proxy"
        httpMethod: "POST"
        uri:
          Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:integration-layer-client-management/invocations"
        responses:
          default:
            statusCode: "201"
        passthroughBehavior: "when_no_match"
        contentHandling: "CONVERT_TO_TEXT"
      security:
        - Authorize: [ ]

  /client/{clientId}:
    description: Operations on a specific client

    delete:
      description: Delete a given client
      parameters:
        - in: path
          name: clientId
          required: true
          schema:
            type: string
      responses:
        204:
          description: Client deleted successfully
        404:
          description: Not available or user not authorized to see this client
        500:
          description: Internal server error
      x-amazon-apigateway-integration:
        httpMethod: "POST"
        uri:
          Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:integration-layer-client-management/invocations"
        responses:
          default:
            statusCode: "204"
        passthroughBehavior: "when_no_match"
        contentHandling: "CONVERT_TO_TEXT"
        type: "aws_proxy"
      security:
        - Authorize: [ ]

  /otp:
    description: OTP API key generation

    parameters:
      - in: query
        name: systemId
        required: true
        schema:
          type: string
        description: Client identifier
        example: '3907f492-3af3-4c0d-a09f-81c6ec0e4b3d'
      - in: query
        name: customerId
        required: true
        schema:
          type: string
        description: Customer Id
        example: '121032'

    post:
      description: Generate OTP API key
      responses:
        200:
          description: OTP API key generated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OTPResponse'
        400:
          description: Missing attribute in the payload
        409:
          description: System already registered with different customerId
        500:
          description: Internal server error
      x-amazon-apigateway-integration:
        type: "aws_proxy"
        httpMethod: "POST"
        uri:
          Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:otp/invocations"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        contentHandling: "CONVERT_TO_TEXT"
      security:
        - Authorize-otp: [ ]

components:
  schemas:
    OnboardClientRequest:
      type: object
      required:
        - publicKey
      properties:
        publicKey:
          type: string
          description: Public key in PEM format
          example: '-----BEGIN PUBLIC KEY-----\nPUBLIC\nKEY\nLINES\nSEPARATED\nWITH\n-----END PUBLIC KEY-----'
    OnboardedClientDetails:
      type: object
      properties:
        client_name:
          type: string
          description: Name of the client (equal to systemId with added timestamp)
          example: '3907f492-3af3-4c0d-a09f-81c6ec0e4b3d_1685686753'
        clientId:
          type: string
          description: Unique identifier of the client
          example: '33333333334444444445555555555555444555555'
        x5c:
          type: string
          description: x5c (X.509 certificate chain) indicates a chain of one or more PKIX certificates
          example: "<redacted>"
    OTPResponse:
      type: object
      properties:
        otp:
          type: string
          description: OTP API key
          example: '<redacted>'

In my virtual environment (venv) the following PyPi dependencies are used:

mkdocs-material==9.1.21
mkdocs-mermaid2-plugin==1.0.6
python-markdown-comments==1.1.0
essentials-openapi[full]==1.0.8
neoteroi-mkdocs==1.0.4
pymdown-extensions==10.1

My environment:

  • OS: macOS Ventura 13.5
  • Python: 3.11.4 (HomeBrew)

Am I missing something?

@volphy volphy changed the title Cannot generate Markdown file from API definition in YAML Cannot generate Markdown file from valid API definition in YAML Aug 7, 2023
@alexmarco
Copy link

alexmarco commented Dec 4, 2023

Same problem.
I have the suspect that is a problem with list structures in get_tag

@bitsondatadev
Copy link

bitsondatadev commented Dec 10, 2024

Same problem. I have the suspect that is a problem with list structures in get_tag

As @alexmarco mentions, the issue is in get_tag.

This code assumes that path items only contain operation items (which would return a python object that has the get() method). Based on the OpenAPI spec we see that the $ref, summary, and description field can be included, as well as, lists of server objects (servers) or parameter to reference mappings (parameters).

In the example above, for instance, the description field is being used and not finding a .get() method on the Python string.

paths:
  /client:
    description: Client onboarding operations

To address this, at the very least we will need to add a check if the path item is indeed an operation and otherwise skip handling it.

The more correct but involved solution is to add handlers for all the different path items.

Update: Also in my case, I have a list of parameters in the definition which gives me AttributeError: 'list' object has no attribute 'get' warning instead of a 'str'.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants