Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions tests/time_tracker_api/api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,24 @@ def test_create_attributes_filter_with_valid_attribute_should_succeed():

assert filter is not None
assert type(filter) is RequestParser


def test_remove_required_constraint():
from time_tracker_api.api import remove_required_constraint
from flask_restplus import fields
from flask_restplus import Namespace

ns = Namespace('todos', description='Namespace for testing')
sample_model = ns.model('Todo', {
'id': fields.Integer(readonly=True, description='The task unique identifier'),
'task': fields.String(required=True, description='The task details'),
'done': fields.Boolean(required=False, description='Has it being done or not')
})

new_model = remove_required_constraint(sample_model)

assert new_model is not sample_model

for attrib in sample_model:
assert new_model[attrib].required is False, "No attribute should be required"
assert new_model[attrib] is not sample_model[attrib], "No attribute should be required"
4 changes: 2 additions & 2 deletions time_tracker_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ def init_app(app: Flask):
from commons.data_access_layer.database import init_app as init_database
init_database(app)

from time_tracker_api.api import api
api.init_app(app)
from time_tracker_api.api import init_app
init_app(app)

if app.config.get('DEBUG'):
app.logger.setLevel(logging.INFO)
Expand Down
4 changes: 2 additions & 2 deletions time_tracker_api/activities/activities_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from flask_restplus._http import HTTPStatus

from time_tracker_api.activities.activities_model import create_dao
from time_tracker_api.api import common_fields, api
from time_tracker_api.api import common_fields, api, remove_required_constraint

faker = Faker()

Expand Down Expand Up @@ -68,7 +68,7 @@ def get(self, id):
return activity_dao.get(id)

@ns.doc('update_activity')
@ns.expect(activity_input)
@ns.expect(remove_required_constraint(activity_input))
@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid format or structure of the activity')
@ns.response(HTTPStatus.CONFLICT, 'An activity already exists with this new data')
@ns.marshal_with(activity)
Expand Down
37 changes: 24 additions & 13 deletions time_tracker_api/api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from azure.cosmos.exceptions import CosmosResourceExistsError, CosmosResourceNotFoundError, CosmosHttpResponseError
from faker import Faker
from flask import current_app as app
from flask import current_app as app, Flask
from flask_restplus import Api, fields, Model
from flask_restplus import namespace
from flask_restplus._http import HTTPStatus
Expand All @@ -22,7 +22,14 @@
)


# Filters
def remove_required_constraint(model: Model):
result = model.resolved
for attrib in result:
result[attrib].required = False

return result


def create_attributes_filter(ns: namespace, model: Model, filter_attrib_names: list) -> RequestParser:
attribs_parser = ns.parser()
model_attributes = model.resolved
Expand Down Expand Up @@ -72,26 +79,30 @@ def __init__(self, *args, **kwargs):
),
}

# APIs
from time_tracker_api.projects import projects_namespace

api.add_namespace(projects_namespace.ns)
def init_app(app: Flask):
api.init_app(app)

from time_tracker_api.projects import projects_namespace

api.add_namespace(projects_namespace.ns)

from time_tracker_api.activities import activities_namespace

from time_tracker_api.activities import activities_namespace
api.add_namespace(activities_namespace.ns)

api.add_namespace(activities_namespace.ns)
from time_tracker_api.time_entries import time_entries_namespace

from time_tracker_api.time_entries import time_entries_namespace
api.add_namespace(time_entries_namespace.ns)

api.add_namespace(time_entries_namespace.ns)
from time_tracker_api.project_types import project_types_namespace

from time_tracker_api.project_types import project_types_namespace
api.add_namespace(project_types_namespace.ns)

api.add_namespace(project_types_namespace.ns)
from time_tracker_api.customers import customers_namespace

from time_tracker_api.customers import customers_namespace
api.add_namespace(customers_namespace.ns)

api.add_namespace(customers_namespace.ns)

"""
Error handlers
Expand Down
4 changes: 2 additions & 2 deletions time_tracker_api/customers/customers_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from flask_restplus import Resource, fields
from flask_restplus._http import HTTPStatus

from time_tracker_api.api import common_fields, api
from time_tracker_api.api import common_fields, api, remove_required_constraint
from time_tracker_api.customers.customers_model import create_dao

faker = Faker()
Expand Down Expand Up @@ -74,7 +74,7 @@ def get(self, id):
@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid format or structure '
'of the attributes of the customer')
@ns.response(HTTPStatus.CONFLICT, 'A customer already exists with this new data')
@ns.expect(customer_input)
@ns.expect(remove_required_constraint(customer_input))
@ns.marshal_with(customer)
def put(self, id):
"""Update a customer"""
Expand Down
4 changes: 2 additions & 2 deletions time_tracker_api/project_types/project_types_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from flask_restplus import Resource, fields
from flask_restplus._http import HTTPStatus

from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID, remove_required_constraint
from time_tracker_api.project_types.project_types_model import create_dao

faker = Faker()
Expand Down Expand Up @@ -94,7 +94,7 @@ def get(self, id):
@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid format or structure '
'of the attributes of the project type')
@ns.response(HTTPStatus.CONFLICT, 'A project type already exists with this new data')
@ns.expect(project_type_input)
@ns.expect(remove_required_constraint(project_type_input))
@ns.marshal_with(project_type)
def put(self, id):
"""Update a project type"""
Expand Down
4 changes: 2 additions & 2 deletions time_tracker_api/projects/projects_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from flask_restplus import Resource, fields
from flask_restplus._http import HTTPStatus

from time_tracker_api.api import common_fields, create_attributes_filter, UUID, api
from time_tracker_api.api import common_fields, create_attributes_filter, UUID, api, remove_required_constraint
from time_tracker_api.projects.projects_model import create_dao

faker = Faker()
Expand Down Expand Up @@ -94,7 +94,7 @@ def get(self, id):
@ns.response(HTTPStatus.BAD_REQUEST, 'Invalid format or structure '
'of the attributes of the project')
@ns.response(HTTPStatus.CONFLICT, 'A project already exists with this new data')
@ns.expect(project_input)
@ns.expect(remove_required_constraint(project_input))
@ns.marshal_with(project)
def put(self, id):
"""Update a project"""
Expand Down
7 changes: 4 additions & 3 deletions time_tracker_api/time_entries/time_entries_namespace.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

from commons.data_access_layer.cosmos_db import current_datetime, datetime_str, current_datetime_str
from commons.data_access_layer.database import COMMENTS_MAX_LENGTH
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID
from time_tracker_api.api import common_fields, create_attributes_filter, api, UUID, NullableString, \
remove_required_constraint
from time_tracker_api.time_entries.time_entries_model import create_dao

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