Skip to content

Commit

Permalink
[add] adding lots of in code docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Animenosekai committed Feb 21, 2023
1 parent d9a42b5 commit 15cb17f
Show file tree
Hide file tree
Showing 40 changed files with 751 additions and 306 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2021 Animenosekai
Copyright (c) 2023 Animenosekai

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion nasse/__main__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
nasse/__main__
The CLI script
The CLI entry
"""

import argparse
Expand Down
8 changes: 8 additions & 0 deletions nasse/config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""
Nasse configuration
"""

import dataclasses
import pathlib
import typing
Expand All @@ -13,6 +17,10 @@ def _alphabetic(string):

@dataclasses.dataclass
class NasseConfig:
"""
A configuration object for a Nasse app
"""

def verify_logger(self):
from nasse.utils.logging import Logger
if self.logger is None:
Expand Down
7 changes: 6 additions & 1 deletion nasse/docs/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
from nasse.docs import curl, example, header, javascript, markdown, postman, python
"""
Automatic Documentation Generation on Nasse
"""

from nasse.docs import (curl, example, header, javascript, markdown, postman,
python)
84 changes: 75 additions & 9 deletions nasse/docs/curl.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,95 @@
"""
Creating `curl` examples
"""

import typing

from nasse import models


def create_curl_example_for_method(endpoint: models.Endpoint, method: str):
def create_curl_example_for_method(endpoint: models.Endpoint, method: str) -> str:
"""
Creates a `curl` example for the given method
Parameters
----------
endpoint: models.Endpoint
The endpoint to create the example from
method: str
The method to create the example for
Returns
-------
str
A usage example for `curl`
"""

def sanitize_backslashes(element: str):
"""
Turns the backslashes into triple backslashes
Parameters
---------
element: str
The element to sanitize
Returns
-------
str
The sanitized element
"""
return str(element).replace("\"", "\\\"")

params = {param.name: param.description or param.name for param in endpoint.params if param.required and (
param.all_methods or method in param.methods)}
headers = {header.name: header.description or header.name for header in endpoint.headers if header.required and (
header.all_methods or method in header.methods)}

params_render = ""
headers_render = ""

if len(params) > 0:
params_render = "\\\n --data-urlencode " + "\\\n --data-urlencode ".join(['"' + param.replace(
"\"", "\\\"") + '=<' + description.replace("\"", "\\\"") + '>"' for param, description in params.items()]) + " "
# ref: https://everything.curl.dev/http/post/url-encode
params_render = "\\\n --data-urlencode " + "\\\n --data-urlencode ".join(
['"' + sanitize_backslashes(param)
+ '=<' + sanitize_backslashes(description)
+ '>"' for param, description in params.items()]
) + " "
if len(headers) <= 0:
params_render += "\\\n "

if len(headers) > 0:
headers_render = "\\\n -H " + '\\\n -H '.join(['"' + header.replace(
"\"", "\\\"") + ': ' + description.replace("\"", "\\\"") + '"' for header, description in headers.items()]) + " "
# ref: https://everything.curl.dev/http/requests/headers
headers_render = "\\\n -H " + '\\\n -H '.join([
'"' + sanitize_backslashes(header)
+ ': ' + sanitize_backslashes(description)
+ '"' for header, description in headers.items()]
) + " "
headers_render += "\\\n "

return '''curl -X {method} {params}{headers}"{path}"'''.format(
method=method, params=params_render, headers=headers_render, path=endpoint.path)
method=method,
params=params_render,
headers=headers_render,
path=endpoint.path
)


def create_curl_example(endpoint: models.Endpoint) -> typing.Dict[str, str]:
"""
Creates a `curl` example command to use the endpoint.
Parameters
----------
endpoint: models.Endpoint
The endpoint to create the example for
def create_curl_example(endpoint: models.Endpoint):
Returns
-------
dict[str, str]
A dictionary of {method: example} values.
"""
results = {}
for method in endpoint.methods:
results[method] = create_curl_example_for_method(
endpoint=endpoint, method=method)
results[method] = create_curl_example_for_method(endpoint=endpoint, method=method)
return results
56 changes: 51 additions & 5 deletions nasse/docs/example.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
"""
Generates response examples
"""

from nasse import models, utils


def _get_type(data):
"""Retrieves the type of the given returning item"""
def _get_type(data: models.Return) -> str:
"""
An internal function to retrieves the type of the given returning item
Parameters
----------
data: models.Return
The return value to get the type from
Returns
-------
"string" | "int" | "float | "bool" | "array" | "object"
The type, when possible
str
When impossible, returns the type as a string
"""
key_type = data.type

if key_type is None:
example = data.example
if example is None:
Expand All @@ -15,9 +34,13 @@ def _get_type(data):
elif isinstance(example, dict):
return "object"
else:
return example.__class__.__name__
try:
return example.__class__.__name__ # should be `str`
except AttributeError:
pass

key_type = str(key_type)
key_type_token = key_type.lower()
key_type_token = key_type.lower().replace(" ", "")
if key_type_token in {"str", "string", "text"}:
return "string"
elif key_type_token in {"int", "integer"}:
Expand All @@ -33,8 +56,29 @@ def _get_type(data):
return key_type


def generate_example(endpoint: models.Endpoint, method: str):
def generate_example(endpoint: models.Endpoint, method: str) -> str:
"""
Generates a JSON response example
Parameters
----------
endpoint: models.Endpoint
The endpoint to get the response example from
method: str
The method to get the response example from
Returns
-------
str
The response example
"""
def get_value(data):
"""
Parameters
----------
data
"""
key_type = _get_type(data)
# if self.returning[key].get("nullable", False) and key_type != "object":
# return None
Expand All @@ -57,6 +101,8 @@ def get_value(data):
if element.all_methods or method in element.methods:
_response_format[element.name] = get_value(element)

# we can't consider using f-strings because they came with py3.6
# pylint: disable=consider-using-f-string
return '''{{
"success": true,
"message": "Successfully processed your request",
Expand Down
141 changes: 24 additions & 117 deletions nasse/docs/header.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,31 @@
"""
Manages GitHub flavored markdown headers
"""

import typing


def header_link(header: str, registry: typing.List[str] = None):
def header_link(header: str, registry: typing.Optional[typing.List[str]] = None) -> str:
"""
- All text is converted to lowercase.
- All non-word text (e.g., punctuation, HTML) is removed.
- All spaces are converted to hyphens.
- Two or more hyphens in a row are converted to one.
- If a header with the same ID has already been generated, a unique incrementing number is appended, starting at 1.
Generates a link from the given header
Note: All text is converted to lowercase.
Note: All non-word text (e.g., punctuation, HTML) is removed.
Note: All spaces are converted to hyphens.
Note: Two or more hyphens in a row are converted to one.
Note: If a header with the same ID has already been generated, a unique incrementing number is appended, starting at 1.
Parameters
----------
header: str
The header to generate the link from
registry: list[str], optional
An internal registry of the different created links
Returns
-------
str
A link to the header
"""
if registry is None:
registry = []
Expand All @@ -29,114 +47,3 @@ def header_link(header: str, registry: typing.List[str] = None):
return "{result}-{count}".format(result=final_result, count=link_count)
else:
return final_result


GETTING_STARTED_HEADER = '''
# {name} API Reference
Welcome to the {name} API Reference.
## Globals
### Response Format
Globally, JSON responses should be formatted as follows (even when critical errors occur)
```json
{{
"success": true,
"message": "We successfully did this!",
"error": null,
"data": {{}}
}}
```
| Field | Description | Nullable |
| ------------ | ------------------------------------------------ | ---------------- |
| `success` | Wether the request was a success or not | False |
| `message` | A message describing what happened | True |
| `error` | The exception name if an error occured | True |
| `data` | The extra data, information asked in the request | False |
### Errors
Multiple Errors can occur, server side or request side.
Specific errors are documented in each endpoint but these are the general errors that can occur on any endpoint:
| Exception | Description | Code |
| --------------------------- | --------------------------------------------------------------------------------------------------------------- | ----- |
| `SERVER_ERROR` | When an error occurs on {name} while processing a request | 500 |
| `MISSING_CONTEXT` | When you are trying to access something which is only available in a Nasse context, and you aren't in one | 500 |
| `INTERNAL_SERVER_ERROR` | When a critical error occurs on the system | 500 |
| `METHOD_NOT_ALLOWED` | When you made a request with the wrong method | 405 |
| `CLIENT_ERROR` | When something is missing or is wrong with the request | 400 |
| `MISSING_VALUE` | When a value is missing from the request | 400 |
| `MISSING_PARAM` | When a parameter is missing from the request | 400 |
| `MISSING_DYNAMIC` | When a dynamic routing value is missing from the requested URL | 400 |
| `MISSING_HEADER` | When a header is missing from the request | 400 |
| `MISSING_COOKIE` | When a cookie is missing from the request | 400 |
| `AUTH_ERROR` | When an error occured while authenticating the request | 403 |
### Authenticated Requests
When a user needs to be logged in, the "Authorization" header needs to be set to the login token provided when logging in.
Alternatively, the "{id}_token" parameter and "__{id}_token" cookie can be used but these won't be prioritized.
If the endpoint is flagged for a "verified only" login, the account won't be fetched from any database but the token will be checked.
### Debug Mode
On debug mode (`-d` or `--debug`), multiple information are passed in the `debug` section of the response and the `DEBUG` log level is selected on the server.
The 'debug' section is available on every type of error, except the ones issued by Flask such as `INTERNAL_SERVER_ERROR`, `METHOD_NOT_ALLOWED`, etc. (they need to do the bare minimum to not raise an exception and therefore breaking the server)
The "call_stack" attribute is enabled only when an error occurs or the `call_stack` parameter is passed with the request.
```json
{{
"success": true,
"message": "We couldn't fullfil your request",
"error": null,
"data": {{
"username": "Animenosekai"
}},
"debug": {{
"time": {{
"global": 0.036757,
"verification": 0.033558,
"authentication": 0.003031,
"processing": 4.9e-05,
"formatting": 0.0001
}},
"ip": "127.0.0.1",
"headers": {{
"Host": "api.{id}.com",
"Connection": "close",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "fr-fr",
"Accept-Encoding": "gzip, deflate, br",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15"
}},
"values": {{}},
"domain": "api.{id}.com",
"logs": [
"1636562693.036563|[INFO] [nasse.receive.Receive.__call__] → Incoming GET request to /account/name from 127.0.0.1",
"1636562693.070008|[ERROR] [nasse.exceptions.base.MissingToken.__init__] An authentication token is missing from the request"
],
"call_stack": [
"pass the 'call_stack' parameter to get the call stack"
]
}}
}}
```
'''


SECTION_HEADER = '''
# {name} Section API Reference
This file lists and explains the different endpoints available in the {name} section.
'''
Loading

0 comments on commit 15cb17f

Please sign in to comment.