Skip to content

Commit

Permalink
Merge pull request #7 from it-goats/feature/ITG-77/more-task-fields
Browse files Browse the repository at this point in the history
[ITG-77] Add more task properties
  • Loading branch information
john-sonz committed Apr 4, 2022
2 parents 9260550 + 28df104 commit 8ab728c
Show file tree
Hide file tree
Showing 14 changed files with 393 additions and 59 deletions.
5 changes: 4 additions & 1 deletion bode/bode/models/task.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import uuid

from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.exc import NoResultFound

from bode.app import db
from bode.models.utc_datetime import UTCDateTime


class Task(db.Model):
__tablename__ = "tasks"

id = db.Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
title = db.Column(db.String(80), nullable=False)
description = db.Column(db.String(1024), nullable=False, server_default="")
due_date = db.Column(UTCDateTime(), nullable=True)

def create(**kwargs):
task = Task(**kwargs)
Expand Down
22 changes: 22 additions & 0 deletions bode/bode/models/utc_datetime.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import datetime

from sqlalchemy.types import DateTime, TypeDecorator


class UTCDateTime(TypeDecorator):
impl = DateTime
cache_ok = True

def process_bind_param(self, value, _):
if value is not None:
if not value.tzinfo:
raise TypeError("tzinfo is required")
value = value.astimezone(datetime.timezone.utc).replace(
tzinfo=None
)
return value

def process_result_value(self, value, _):
if value is not None:
value = value.replace(tzinfo=datetime.timezone.utc)
return value
15 changes: 15 additions & 0 deletions bode/bode/resources/base_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from marshmallow import Schema


def camelcase(s):
parts = iter(s.split("_"))
return next(parts) + "".join(i.title() for i in parts)


class BaseSchema(Schema):
"""Schema that uses camel-case for its external representation
and snake-case for its internal representation.
"""

def on_bind_field(self, field_name, field_obj):
field_obj.data_key = camelcase(field_obj.data_key or field_name)
9 changes: 4 additions & 5 deletions bode/bode/resources/tasks/api.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from flask import abort
from flask.views import MethodView
from flask_smorest import Blueprint
from sqlalchemy.orm.exc import NoResultFound
from flask_smorest import Blueprint, abort
from sqlalchemy.exc import DataError
from sqlalchemy.orm.exc import NoResultFound

from bode.models.task import Task
from bode.resources.tasks.schemas import TaskSchema
from bode.resources.tasks.schemas import TaskInputSchema, TaskSchema

blueprint = Blueprint("tasks", "tasks", url_prefix="/tasks")

Expand All @@ -16,7 +15,7 @@ class Tasks(MethodView):
def get(self):
return Task.query.all()

@blueprint.arguments(TaskSchema)
@blueprint.arguments(TaskInputSchema)
@blueprint.response(201, TaskSchema)
def post(self, task_data):
return Task.create(**task_data)
Expand Down
16 changes: 13 additions & 3 deletions bode/bode/resources/tasks/schemas.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
from marshmallow import Schema, fields, validate
from marshmallow import fields, validate

from bode.resources.base_schema import BaseSchema

class TaskSchema(Schema):

class TaskInputSchema(BaseSchema):
title = fields.String(validate=validate.Length(1, 80), required=True)
description = fields.String(validate=validate.Length(0, 1024), default="")
due_date = fields.DateTime(allow_none=True)


class TaskSchema(BaseSchema):
id = fields.UUID(dump_only=True)
title = fields.String(validate=validate.Length(1, 80))
title = fields.String()
description = fields.String()
due_date = fields.DateTime()
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Add due date and description to task model
Revision ID: 9b8806b556b8
Revises: 4daafbe3fd77
Create Date: 2022-04-03 19:53:56.792053
"""
import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision = "9b8806b556b8"
down_revision = "4daafbe3fd77"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"tasks",
sa.Column(
"description",
sa.String(length=1024),
server_default="",
nullable=False,
),
)
op.add_column(
"tasks",
sa.Column("due_date", sa.DateTime(timezone=False), nullable=True),
)
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("tasks", "due_date")
op.drop_column("tasks", "description")
# ### end Alembic commands ###
Loading

0 comments on commit 8ab728c

Please sign in to comment.