Skip to content

Commit cec9f4c

Browse files
authored
Merge pull request #113 from ioet/fix/ignore-required-fields-when-update#112
Fix issues required with model fields
2 parents 5bee71f + 36563ee commit cec9f4c

File tree

8 files changed

+59
-26
lines changed

8 files changed

+59
-26
lines changed

tests/time_tracker_api/api_test.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,24 @@ def test_create_attributes_filter_with_valid_attribute_should_succeed():
2222

2323
assert filter is not None
2424
assert type(filter) is RequestParser
25+
26+
27+
def test_remove_required_constraint():
28+
from time_tracker_api.api import remove_required_constraint
29+
from flask_restplus import fields
30+
from flask_restplus import Namespace
31+
32+
ns = Namespace('todos', description='Namespace for testing')
33+
sample_model = ns.model('Todo', {
34+
'id': fields.Integer(readonly=True, description='The task unique identifier'),
35+
'task': fields.String(required=True, description='The task details'),
36+
'done': fields.Boolean(required=False, description='Has it being done or not')
37+
})
38+
39+
new_model = remove_required_constraint(sample_model)
40+
41+
assert new_model is not sample_model
42+
43+
for attrib in sample_model:
44+
assert new_model[attrib].required is False, "No attribute should be required"
45+
assert new_model[attrib] is not sample_model[attrib], "No attribute should be required"

time_tracker_api/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@ def init_app(app: Flask):
3838
from commons.data_access_layer.database import init_app as init_database
3939
init_database(app)
4040

41-
from time_tracker_api.api import api
42-
api.init_app(app)
41+
from time_tracker_api.api import init_app
42+
init_app(app)
4343

4444
if app.config.get('DEBUG'):
4545
app.logger.setLevel(logging.INFO)

time_tracker_api/activities/activities_namespace.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from flask_restplus._http import HTTPStatus
44

55
from time_tracker_api.activities.activities_model import create_dao
6-
from time_tracker_api.api import common_fields, api
6+
from time_tracker_api.api import common_fields, api, remove_required_constraint
77

88
faker = Faker()
99

@@ -68,7 +68,7 @@ def get(self, id):
6868
return activity_dao.get(id)
6969

7070
@ns.doc('update_activity')
71-
@ns.expect(activity_input)
71+
@ns.expect(remove_required_constraint(activity_input))
7272
@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid format or structure of the activity')
7373
@ns.response(HTTPStatus.CONFLICT, 'An activity already exists with this new data')
7474
@ns.marshal_with(activity)

time_tracker_api/api.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from azure.cosmos.exceptions import CosmosResourceExistsError, CosmosResourceNotFoundError, CosmosHttpResponseError
22
from faker import Faker
3-
from flask import current_app as app
3+
from flask import current_app as app, Flask
44
from flask_restplus import Api, fields, Model
55
from flask_restplus import namespace
66
from flask_restplus._http import HTTPStatus
@@ -22,7 +22,14 @@
2222
)
2323

2424

25-
# Filters
25+
def remove_required_constraint(model: Model):
26+
result = model.resolved
27+
for attrib in result:
28+
result[attrib].required = False
29+
30+
return result
31+
32+
2633
def create_attributes_filter(ns: namespace, model: Model, filter_attrib_names: list) -> RequestParser:
2734
attribs_parser = ns.parser()
2835
model_attributes = model.resolved
@@ -72,26 +79,30 @@ def __init__(self, *args, **kwargs):
7279
),
7380
}
7481

75-
# APIs
76-
from time_tracker_api.projects import projects_namespace
7782

78-
api.add_namespace(projects_namespace.ns)
83+
def init_app(app: Flask):
84+
api.init_app(app)
85+
86+
from time_tracker_api.projects import projects_namespace
87+
88+
api.add_namespace(projects_namespace.ns)
89+
90+
from time_tracker_api.activities import activities_namespace
7991

80-
from time_tracker_api.activities import activities_namespace
92+
api.add_namespace(activities_namespace.ns)
8193

82-
api.add_namespace(activities_namespace.ns)
94+
from time_tracker_api.time_entries import time_entries_namespace
8395

84-
from time_tracker_api.time_entries import time_entries_namespace
96+
api.add_namespace(time_entries_namespace.ns)
8597

86-
api.add_namespace(time_entries_namespace.ns)
98+
from time_tracker_api.project_types import project_types_namespace
8799

88-
from time_tracker_api.project_types import project_types_namespace
100+
api.add_namespace(project_types_namespace.ns)
89101

90-
api.add_namespace(project_types_namespace.ns)
102+
from time_tracker_api.customers import customers_namespace
91103

92-
from time_tracker_api.customers import customers_namespace
104+
api.add_namespace(customers_namespace.ns)
93105

94-
api.add_namespace(customers_namespace.ns)
95106

96107
"""
97108
Error handlers

time_tracker_api/customers/customers_namespace.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from flask_restplus import Resource, fields
33
from flask_restplus._http import HTTPStatus
44

5-
from time_tracker_api.api import common_fields, api
5+
from time_tracker_api.api import common_fields, api, remove_required_constraint
66
from time_tracker_api.customers.customers_model import create_dao
77

88
faker = Faker()
@@ -74,7 +74,7 @@ def get(self, id):
7474
@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid format or structure '
7575
'of the attributes of the customer')
7676
@ns.response(HTTPStatus.CONFLICT, 'A customer already exists with this new data')
77-
@ns.expect(customer_input)
77+
@ns.expect(remove_required_constraint(customer_input))
7878
@ns.marshal_with(customer)
7979
def put(self, id):
8080
"""Update a customer"""

time_tracker_api/project_types/project_types_namespace.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from flask_restplus import Resource, fields
33
from flask_restplus._http import HTTPStatus
44

5-
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID
5+
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID, remove_required_constraint
66
from time_tracker_api.project_types.project_types_model import create_dao
77

88
faker = Faker()
@@ -94,7 +94,7 @@ def get(self, id):
9494
@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid format or structure '
9595
'of the attributes of the project type')
9696
@ns.response(HTTPStatus.CONFLICT, 'A project type already exists with this new data')
97-
@ns.expect(project_type_input)
97+
@ns.expect(remove_required_constraint(project_type_input))
9898
@ns.marshal_with(project_type)
9999
def put(self, id):
100100
"""Update a project type"""

time_tracker_api/projects/projects_namespace.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from flask_restplus import Resource, fields
33
from flask_restplus._http import HTTPStatus
44

5-
from time_tracker_api.api import common_fields, create_attributes_filter, UUID, api
5+
from time_tracker_api.api import common_fields, create_attributes_filter, UUID, api, remove_required_constraint
66
from time_tracker_api.projects.projects_model import create_dao
77

88
faker = Faker()
@@ -94,7 +94,7 @@ def get(self, id):
9494
@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid format or structure '
9595
'of the attributes of the project')
9696
@ns.response(HTTPStatus.CONFLICT, 'A project already exists with this new data')
97-
@ns.expect(project_input)
97+
@ns.expect(remove_required_constraint(project_input))
9898
@ns.marshal_with(project)
9999
def put(self, id):
100100
"""Update a project"""

time_tracker_api/time_entries/time_entries_namespace.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
from commons.data_access_layer.cosmos_db import current_datetime, datetime_str, current_datetime_str
88
from commons.data_access_layer.database import COMMENTS_MAX_LENGTH
9-
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID
9+
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID, NullableString, \
10+
remove_required_constraint
1011
from time_tracker_api.time_entries.time_entries_model import create_dao
1112

1213
faker = Faker()
@@ -48,7 +49,7 @@
4849
description='When the user ended doing this activity',
4950
example=current_datetime_str(),
5051
),
51-
'uri': fields.String(
52+
'uri': NullableString(
5253
title='Uniform Resource identifier',
5354
description='Either identifier or locator of a resource in the Internet that helps to understand'
5455
' what this time entry was about. For example, A Jira ticket, a Github issue, a Google document.',
@@ -146,7 +147,7 @@ def get(self, id):
146147
'of the attributes of the time entry')
147148
@ns.response(HTTPStatus.CONFLICT, 'A time entry already exists with this new data or there'
148149
' is a bad reference for the project or activity')
149-
@ns.expect(time_entry_input)
150+
@ns.expect(remove_required_constraint(time_entry_input))
150151
@ns.marshal_with(time_entry)
151152
def put(self, id):
152153
"""Update a time entry"""

0 commit comments

Comments
 (0)