From 3ae98bf8ec4483661e46536d2c964a6a864ff96d Mon Sep 17 00:00:00 2001 From: Sebastian Aranda Sanchez Date: Wed, 25 Oct 2023 11:50:24 -0300 Subject: [PATCH 1/2] Add new category and time_lost_type params --- ...dbdb6f_add_category_and_time_lost_type_.py | 55 +++++++++++++++++++ src/narrativelog/create_tables.py | 15 +++++ src/narrativelog/message.py | 7 +++ src/narrativelog/routers/add_message.py | 12 ++++ src/narrativelog/routers/edit_message.py | 12 ++++ src/narrativelog/routers/find_messages.py | 28 ++++++++++ src/narrativelog/testutils.py | 9 ++- tests/test_add_message.py | 4 ++ tests/test_edit_message.py | 5 +- tests/test_find_messages.py | 4 +- 10 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 alembic/versions/54f755dbdb6f_add_category_and_time_lost_type_.py diff --git a/alembic/versions/54f755dbdb6f_add_category_and_time_lost_type_.py b/alembic/versions/54f755dbdb6f_add_category_and_time_lost_type_.py new file mode 100644 index 0000000..a8a4ca3 --- /dev/null +++ b/alembic/versions/54f755dbdb6f_add_category_and_time_lost_type_.py @@ -0,0 +1,55 @@ +"""add category and time_lost_type parameters + +Revision ID: 54f755dbdb6f +Revises: d9606992ad8d +Create Date: 2023-10-24 14:19:37.665359 + +""" +import logging + +import sqlalchemy as sa +import sqlalchemy.types as saty + +from alembic import op + +# revision identifiers, used by Alembic. +revision = "54f755dbdb6f" +down_revision = "d9606992ad8d" +branch_labels = None +depends_on = None + + +MESSAGE_TABLE_NAME = "message" +CATEGORY_LEN = 50 +TIME_LOST_TYPE_LEN = 50 + + +def upgrade(log: logging.Logger, table_names: set[str]) -> None: + if MESSAGE_TABLE_NAME not in table_names: + log.info(f"No {MESSAGE_TABLE_NAME} table; nothing to do") + return + log.info("Add 'category' column and add 'time_lost_type' column") + op.add_column( + table_name=MESSAGE_TABLE_NAME, + column=sa.Column( + "category", saty.String(length=CATEGORY_LEN), nullable=True + ), + ) + op.add_column( + table_name=MESSAGE_TABLE_NAME, + column=sa.Column( + "time_lost_type", + saty.String(length=TIME_LOST_TYPE_LEN), + nullable=True, + ), + ) + + +def downgrade(log: logging.Logger, table_names: set[str]) -> None: + if MESSAGE_TABLE_NAME not in table_names: + log.info(f"No {MESSAGE_TABLE_NAME} table; nothing to do") + return + + log.info("Drop 'category' column and drop 'time_lost_type' column") + op.drop_column(table_name=MESSAGE_TABLE_NAME, column_name="category") + op.drop_column(table_name=MESSAGE_TABLE_NAME, column_name="time_lost_type") diff --git a/src/narrativelog/create_tables.py b/src/narrativelog/create_tables.py index 1069aff..9ed05c0 100644 --- a/src/narrativelog/create_tables.py +++ b/src/narrativelog/create_tables.py @@ -13,6 +13,12 @@ # Length of the site_id field. SITE_ID_LEN = 16 +# Length of the category field. +CATEGORY_LEN = 50 + +# Length of the time_lost_type field. +TIME_LOST_TYPE_LEN = 50 + def create_message_table(metadata: sa.MetaData) -> sa.Table: """Make a model of the narrativelog message table. @@ -59,6 +65,13 @@ def create_message_table(metadata: sa.MetaData) -> sa.Table: sa.Column("cscs", saty.ARRAY(sa.Text), nullable=True), # Added 2022-07-37 sa.Column("date_end", saty.DateTime(), nullable=True), + # Added 2023-10-24 + sa.Column("category", saty.String(length=CATEGORY_LEN), nullable=True), + sa.Column( + "time_lost_type", + saty.String(length=TIME_LOST_TYPE_LEN), + nullable=True, + ), # Constraints sa.ForeignKeyConstraint(["parent_id"], ["message.id"]), ) @@ -70,6 +83,8 @@ def create_message_table(metadata: sa.MetaData) -> sa.Table: "user_id", "is_valid", "date_added", + "category", + "time_lost_type", ): sa.Index(f"idx_{name}", table.columns[name]) diff --git a/src/narrativelog/message.py b/src/narrativelog/message.py index 199a633..d009a4e 100644 --- a/src/narrativelog/message.py +++ b/src/narrativelog/message.py @@ -71,6 +71,13 @@ class Message(BaseModel): title="Zero or more primary hardware component names. " "Each entry should be a valid component name entry on the OBS jira project.", ) + # Added 2023-10-24 + category: None | str = Field( + title="Category of message.", + ) + time_lost_type: None | str = Field( + title="Type of time lost.", + ) class Config: orm_mode = True diff --git a/src/narrativelog/routers/add_message.py b/src/narrativelog/routers/add_message.py index e4ac58b..74c41c7 100644 --- a/src/narrativelog/routers/add_message.py +++ b/src/narrativelog/routers/add_message.py @@ -24,6 +24,16 @@ async def add_message( level: int = fastapi.Body( ..., description="Message level; a python logging level." ), + category: None + | str = fastapi.Body( + default=None, + description="Message category; a string.", + ), + time_lost_type: None + | str = fastapi.Body( + default=None, + description="Type of lost time.", + ), tags: list[str] = fastapi.Body( default=[], description="Tags describing the message. " + TAG_DESCRIPTION, @@ -140,6 +150,8 @@ async def add_message( systems=systems, subsystems=subsystems, cscs=cscs, + category=category, + time_lost_type=time_lost_type, ) .returning(sa.literal_column("*")) ) diff --git a/src/narrativelog/routers/edit_message.py b/src/narrativelog/routers/edit_message.py index 4275c4e..84b2509 100644 --- a/src/narrativelog/routers/edit_message.py +++ b/src/narrativelog/routers/edit_message.py @@ -24,6 +24,16 @@ async def edit_message( default=None, description="Message level; a python logging level.", ), + category: None + | str = fastapi.Body( + default=None, + description="Message category; a string.", + ), + time_lost_type: None + | str = fastapi.Body( + default=None, + description="Type of lost time.", + ), tags: None | list[str] = fastapi.Body( default=None, @@ -133,6 +143,8 @@ async def edit_message( "components", "primary_software_components", "primary_hardware_components", + "category", + "time_lost_type", "urls", "time_lost", "date_begin", diff --git a/src/narrativelog/routers/find_messages.py b/src/narrativelog/routers/find_messages.py index 878037b..e345e88 100644 --- a/src/narrativelog/routers/find_messages.py +++ b/src/narrativelog/routers/find_messages.py @@ -57,6 +57,34 @@ async def find_messages( description="User agents (which app created the message). " "Repeat the parameter for each value.", ), + categories: None + | list[str] = fastapi.Query( + default=None, + description="Categories, or fragments of categories, " + "of which at least one must be present. " + "Repeat the parameter for each value.", + ), + exclude_categories: None + | list[str] = fastapi.Query( + default=None, + description="Categories, or fragments of categories, " + "of which all must be absent. " + "Repeat the parameter for each value.", + ), + time_lost_types: None + | list[str] = fastapi.Query( + default=None, + description="Time lost types, or fragments of time lost types, " + "of which at least one must be present. " + "Repeat the parameter for each value.", + ), + exclude_time_lost_types: None + | list[str] = fastapi.Query( + default=None, + description="Time lost types, or fragments of time lost types, " + "of which all must be absent. " + "Repeat the parameter for each value.", + ), tags: None | list[str] = fastapi.Query( default=None, diff --git a/src/narrativelog/testutils.py b/src/narrativelog/testutils.py index 652b750..4673cba 100644 --- a/src/narrativelog/testutils.py +++ b/src/narrativelog/testutils.py @@ -31,7 +31,11 @@ from sqlalchemy.ext.asyncio import create_async_engine from . import main, shared_state -from .create_tables import create_jira_fields_table, create_message_table +from .create_tables import ( + CATEGORY_LEN, + create_jira_fields_table, + create_message_table, +) from .message import JIRA_FIELDS, MESSAGE_FIELDS # Range of dates for random messages. @@ -392,6 +396,9 @@ def random_message() -> MessageDictT: primary_hardware_components=random_strings( TEST_PRIMARY_HARDWARE_COMPONENTS ), + # Added 2023-10-24 + category=random_str(nchar=CATEGORY_LEN), + time_lost_type=random.choice(["fault", "weather"]), ) # Check that we have set all fields (not necessarily in order). diff --git a/tests/test_add_message.py b/tests/test_add_message.py index 8dc6c5d..e2b051d 100644 --- a/tests/test_add_message.py +++ b/tests/test_add_message.py @@ -90,6 +90,10 @@ async def test_add_message(self) -> None: add_args_full["primary_hardware_components"] = random_strings( TEST_PRIMARY_HARDWARE_COMPONENTS ) + add_args_full["category"] = "test" + add_args_full["time_lost_type"] = random.choice( + ["fault", "weather"] + ) response = await client.post( "/narrativelog/messages", json=add_args_full ) diff --git a/tests/test_edit_message.py b/tests/test_edit_message.py index 3bcb75e..e81a380 100644 --- a/tests/test_edit_message.py +++ b/tests/test_edit_message.py @@ -34,10 +34,9 @@ def assert_good_edit_response( ( "id", "site_id", - "is_valid", "parent_id", - "date_added", "is_valid", + "date_added", "date_invalidated", ) ): @@ -86,6 +85,8 @@ async def test_edit_message(self) -> None: "new primary_hardware_component 1", "new primary_hardware_component 2", ], + category="New category", + time_lost_type=random.choice(["fault", "weather"]), ) # Repeatedly edit the old message. Each time # add a new version of the message with one field omitted, diff --git a/tests/test_find_messages.py b/tests/test_find_messages.py index 09a21ac..11e9f38 100644 --- a/tests/test_find_messages.py +++ b/tests/test_find_messages.py @@ -115,8 +115,6 @@ def assert_two_messages_ordered( for key in order_by: if key.startswith("-"): field = key[1:] - val1 = message1[field] - val2 = message2[field] desired_cmp_result = 1 else: field = key @@ -458,6 +456,8 @@ def is_valid_predicate(message: MessageDictT) -> bool: "level", "user_id", "user_agent", + "category", + "time_lost_type", ) ) for field, prefix in itertools.product(fields, ("", "-")): From b350e30e34aea9a787bfed08adf1e929fb075e47 Mon Sep 17 00:00:00 2001 From: Sebastian Aranda Sanchez Date: Wed, 25 Oct 2023 16:28:00 -0300 Subject: [PATCH 2/2] Update CHANGELOG --- CHANGELOG.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6c4868c..13405c9 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -2,6 +2,11 @@ Change Log ========== +0.6.0 +----- + +* Add new parameters: ``category`` and ``time_lost_type``. + 0.5.1 -----