Skip to content

Commit 31fe4d1

Browse files
Merge pull request #3 from CodeSignal/swagger
Swagger page
2 parents 86ae6ef + 0858d9e commit 31fe4d1

File tree

4 files changed

+312
-5
lines changed

4 files changed

+312
-5
lines changed

app/main.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from utils.config import load_config, load_initial_todos
99
from utils.auth import setup_auth_config
1010
from services.auth_service import init_auth_service
11+
from flasgger import Swagger
1112
import secrets
1213

1314
def create_app(auth_config):
@@ -32,7 +33,26 @@ def create_app(auth_config):
3233
app.config['SECRET_KEY'] = secrets.token_hex(32) # Generate secure random secret key
3334
app.config['auth_config'] = auth_config
3435
app.config['initial_todos'] = load_initial_todos() # Load initial todos from config file
35-
36+
37+
# Configure Swagger
38+
template = {
39+
"swagger": "2.0",
40+
"info": {
41+
"title": "Todo API",
42+
"description": "A RESTful API for managing todos and notes",
43+
"version": "1.0.0"
44+
}
45+
}
46+
47+
app.config['SWAGGER'] = {
48+
'title': 'Todo API',
49+
'uiversion': 3,
50+
'specs_route': '/',
51+
'url_prefix': '/swagger'
52+
}
53+
54+
Swagger(app, template=template)
55+
3656
# Set up authentication
3757
init_auth_routes(auth_config)
3858
auth_middleware = AuthMiddleware(auth_config)

app/routes/notes.py

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,73 @@
55

66
@notes_bp.route("", methods=["POST"])
77
def upload_note():
8-
"""Upload a new note in .txt format"""
8+
"""Upload a new note in .txt format
9+
---
10+
tags:
11+
- notes
12+
parameters:
13+
- name: file
14+
in: formData
15+
type: file
16+
required: true
17+
description: Text file to upload. Must be .txt format, max size 1MB
18+
responses:
19+
201:
20+
description: Note created successfully
21+
schema:
22+
type: object
23+
properties:
24+
message:
25+
type: string
26+
description: Success message
27+
note_name:
28+
type: string
29+
description: Name of the uploaded note
30+
400:
31+
description: Invalid request - empty file or wrong format
32+
"""
933
return NoteService.upload_note(request)
1034

1135
@notes_bp.route("/<note_name>", methods=["GET"])
1236
def download_note(note_name):
13-
"""Download an existing note by its name"""
37+
"""Download an existing note by its name
38+
---
39+
tags:
40+
- notes
41+
parameters:
42+
- name: note_name
43+
in: path
44+
type: string
45+
required: true
46+
description: Name of the note to download
47+
responses:
48+
200:
49+
description: Note file content
50+
content:
51+
text/plain:
52+
schema:
53+
type: string
54+
404:
55+
description: Note not found
56+
"""
1457
return NoteService.download_note(note_name)
1558

1659
@notes_bp.route("/<note_name>", methods=["DELETE"])
1760
def delete_note(note_name):
18-
"""Delete an existing note by its name"""
61+
"""Delete an existing note by its name
62+
---
63+
tags:
64+
- notes
65+
parameters:
66+
- name: note_name
67+
in: path
68+
type: string
69+
required: true
70+
description: Name of the note to delete
71+
responses:
72+
204:
73+
description: Note deleted successfully
74+
404:
75+
description: Note not found
76+
"""
1977
return NoteService.delete_note(note_name)

app/routes/todos.py

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,252 @@
55

66
@todos_bp.route("", methods=["GET"])
77
def get_all_todos():
8+
"""Get all todos with optional filtering and pagination
9+
---
10+
tags:
11+
- todos
12+
parameters:
13+
- name: done
14+
in: query
15+
type: boolean
16+
required: false
17+
description: Filter by completion status
18+
- name: title
19+
in: query
20+
type: string
21+
required: false
22+
description: Filter by TODO item title prefix
23+
- name: page
24+
in: query
25+
type: integer
26+
required: false
27+
description: Page number for pagination (starts at 1)
28+
- name: limit
29+
in: query
30+
type: integer
31+
required: false
32+
description: Number of items per page
33+
responses:
34+
200:
35+
description: List of todo items
36+
schema:
37+
type: array
38+
items:
39+
type: object
40+
properties:
41+
id:
42+
type: integer
43+
description: The todo ID
44+
title:
45+
type: string
46+
description: The todo title
47+
done:
48+
type: boolean
49+
description: Whether the todo is completed
50+
description:
51+
type: string
52+
description: Detailed todo description
53+
"""
854
return TodoService.get_all_todos(request)
955

1056
@todos_bp.route("<int:todo_id>", methods=["GET"])
1157
def get_todo(todo_id):
58+
"""Get a specific todo by ID
59+
---
60+
tags:
61+
- todos
62+
parameters:
63+
- name: todo_id
64+
in: path
65+
type: integer
66+
required: true
67+
description: ID of the todo to retrieve
68+
responses:
69+
200:
70+
description: Todo details
71+
schema:
72+
type: object
73+
properties:
74+
id:
75+
type: integer
76+
description: The todo ID
77+
title:
78+
type: string
79+
description: The todo title
80+
done:
81+
type: boolean
82+
description: Whether the todo is completed
83+
description:
84+
type: string
85+
description: Detailed todo description
86+
404:
87+
description: Todo not found
88+
"""
1289
return TodoService.get_todo(todo_id)
1390

1491
@todos_bp.route("", methods=["POST"])
1592
def add_todo():
93+
"""Add a new TODO item
94+
---
95+
tags:
96+
- todos
97+
parameters:
98+
- name: body
99+
in: body
100+
required: true
101+
schema:
102+
type: object
103+
required:
104+
- title
105+
properties:
106+
title:
107+
type: string
108+
description: The TODO item title
109+
done:
110+
type: boolean
111+
description: Completion status. Defaults to false if not provided
112+
description:
113+
type: string
114+
description: Detailed TODO item description
115+
responses:
116+
201:
117+
description: Created todo item
118+
schema:
119+
type: object
120+
properties:
121+
id:
122+
type: integer
123+
description: The todo ID
124+
title:
125+
type: string
126+
description: The todo title
127+
done:
128+
type: boolean
129+
description: Whether the todo is completed
130+
description:
131+
type: string
132+
description: Detailed todo description
133+
400:
134+
description: Invalid request - missing title
135+
"""
16136
return TodoService.add_todo(request)
17137

18138
@todos_bp.route("<int:todo_id>", methods=["PUT"])
19139
def edit_todo(todo_id):
140+
"""Replace an existing TODO item (all fields required)
141+
---
142+
tags:
143+
- todos
144+
parameters:
145+
- name: todo_id
146+
in: path
147+
type: integer
148+
required: true
149+
description: ID of the todo to update
150+
- name: body
151+
in: body
152+
required: true
153+
schema:
154+
type: object
155+
required:
156+
- title
157+
- done
158+
- description
159+
properties:
160+
title:
161+
type: string
162+
description: The TODO item title
163+
done:
164+
type: boolean
165+
description: Completion status
166+
description:
167+
type: string
168+
description: Detailed TODO item description
169+
responses:
170+
200:
171+
description: Updated todo item
172+
schema:
173+
type: object
174+
properties:
175+
id:
176+
type: integer
177+
title:
178+
type: string
179+
done:
180+
type: boolean
181+
description:
182+
type: string
183+
400:
184+
description: Invalid request (missing required fields)
185+
404:
186+
description: Todo not found
187+
"""
20188
return TodoService.edit_todo(todo_id, request)
21189

22190
@todos_bp.route("<int:todo_id>", methods=["PATCH"])
23191
def patch_todo(todo_id):
192+
"""Update part of a TODO item (any field optional)
193+
---
194+
tags:
195+
- todos
196+
parameters:
197+
- name: todo_id
198+
in: path
199+
type: integer
200+
required: true
201+
description: ID of the todo to update
202+
- name: body
203+
in: body
204+
required: true
205+
schema:
206+
type: object
207+
properties:
208+
title:
209+
type: string
210+
description: The TODO item title
211+
done:
212+
type: boolean
213+
description: Completion status
214+
description:
215+
type: string
216+
description: Detailed TODO item description
217+
responses:
218+
200:
219+
description: Updated todo item
220+
schema:
221+
type: object
222+
properties:
223+
id:
224+
type: integer
225+
title:
226+
type: string
227+
done:
228+
type: boolean
229+
description:
230+
type: string
231+
400:
232+
description: Invalid request (empty body)
233+
404:
234+
description: Todo not found
235+
"""
24236
return TodoService.patch_todo(todo_id, request)
25237

26238
@todos_bp.route("<int:todo_id>", methods=["DELETE"])
27239
def delete_todo(todo_id):
240+
"""Delete a TODO item
241+
---
242+
tags:
243+
- todos
244+
parameters:
245+
- name: todo_id
246+
in: path
247+
type: integer
248+
required: true
249+
description: ID of the todo to delete
250+
responses:
251+
204:
252+
description: Todo deleted successfully
253+
404:
254+
description: Todo not found
255+
"""
28256
return TodoService.delete_todo(todo_id)

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
Flask==2.2.5
22
PyJWT==2.8.0
3-
PyYAML==6.0.1
3+
PyYAML==6.0.1
4+
flasgger==0.9.7

0 commit comments

Comments
 (0)