From a0e8be5b54ca9186d0dae2bd38b3617dba1dc423 Mon Sep 17 00:00:00 2001 From: Veda Karteeka Gogineni Date: Tue, 9 Jan 2024 13:13:11 -0800 Subject: [PATCH 1/8] provide count of keywords used --- app/modules/keywords/schemas.py | 7 +++++++ tests/modules/keywords/resources/test_keywords.py | 2 ++ 2 files changed, 9 insertions(+) diff --git a/app/modules/keywords/schemas.py b/app/modules/keywords/schemas.py index 55c1074de..2d9e1c6e8 100644 --- a/app/modules/keywords/schemas.py +++ b/app/modules/keywords/schemas.py @@ -6,6 +6,7 @@ from flask_restx_patched import ModelSchema +from flask_marshmallow import base_fields from .models import Keyword @@ -14,6 +15,10 @@ class BaseKeywordSchema(ModelSchema): """ Base Keyword schema exposes only the most general fields. """ + usageCount = base_fields.Function( + lambda kw: kw.number_referenced_dependencies(), + dump_only=True # This is a read-only field + ) class Meta: # pylint: disable=missing-docstring @@ -22,6 +27,8 @@ class Meta: Keyword.guid.key, Keyword.value.key, Keyword.source.key, + 'usageCount', + ) dump_only = (Keyword.guid.key,) diff --git a/tests/modules/keywords/resources/test_keywords.py b/tests/modules/keywords/resources/test_keywords.py index aeab94849..8e05bc8da 100644 --- a/tests/modules/keywords/resources/test_keywords.py +++ b/tests/modules/keywords/resources/test_keywords.py @@ -70,6 +70,8 @@ def test_modify_keyword(db, flask_app_client, researcher_1, staff_user): # doublecheck by reading back in response = keyword_utils.read_keyword(flask_app_client, researcher_1, guid) assert response.json.get('value', None) == val2 + assert response.json.get('usageCount', None) == 0 + # both of these should not be allowed (403) response = keyword_utils.patch_keyword( From 1e0d9d432e2c8d37f1dc8920b08749658d9fed3e Mon Sep 17 00:00:00 2001 From: Veda Karteeka Gogineni Date: Wed, 10 Jan 2024 12:16:44 -0800 Subject: [PATCH 2/8] Add usageCount to DetailedKeywordSchema --- app/modules/keywords/resources.py | 2 +- app/modules/keywords/schemas.py | 15 ++++++--------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/app/modules/keywords/resources.py b/app/modules/keywords/resources.py index 9d29147d4..aec892ddf 100644 --- a/app/modules/keywords/resources.py +++ b/app/modules/keywords/resources.py @@ -28,7 +28,7 @@ class Keywords(Resource): Manipulations with Keywords. """ - @api.response(schemas.BaseKeywordSchema(many=True)) + @api.response(schemas.DetailedKeywordSchema(many=True)) @api.paginate() def get(self, args): """ diff --git a/app/modules/keywords/schemas.py b/app/modules/keywords/schemas.py index 2d9e1c6e8..f7cea4748 100644 --- a/app/modules/keywords/schemas.py +++ b/app/modules/keywords/schemas.py @@ -15,10 +15,6 @@ class BaseKeywordSchema(ModelSchema): """ Base Keyword schema exposes only the most general fields. """ - usageCount = base_fields.Function( - lambda kw: kw.number_referenced_dependencies(), - dump_only=True # This is a read-only field - ) class Meta: # pylint: disable=missing-docstring @@ -27,7 +23,6 @@ class Meta: Keyword.guid.key, Keyword.value.key, Keyword.source.key, - 'usageCount', ) dump_only = (Keyword.guid.key,) @@ -37,13 +32,15 @@ class DetailedKeywordSchema(BaseKeywordSchema): """ Detailed Keyword schema exposes all useful fields. """ + usageCount = base_fields.Function( + lambda kw: kw.number_referenced_dependencies(), + dump_only=True # This is a read-only field + ) + class Meta(BaseKeywordSchema.Meta): fields = BaseKeywordSchema.Meta.fields + ( - Keyword.created.key, - Keyword.updated.key, + 'usageCount', ) dump_only = BaseKeywordSchema.Meta.dump_only + ( - Keyword.created.key, - Keyword.updated.key, ) From 11a42715b5fa923328a43b2dbee52fe4179bd0e3 Mon Sep 17 00:00:00 2001 From: Veda Karteeka Gogineni Date: Wed, 10 Jan 2024 13:21:55 -0800 Subject: [PATCH 3/8] Added created and updated fields in DetailedKeywordSchema --- app/modules/keywords/schemas.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/modules/keywords/schemas.py b/app/modules/keywords/schemas.py index f7cea4748..afd04c19c 100644 --- a/app/modules/keywords/schemas.py +++ b/app/modules/keywords/schemas.py @@ -40,7 +40,11 @@ class DetailedKeywordSchema(BaseKeywordSchema): class Meta(BaseKeywordSchema.Meta): fields = BaseKeywordSchema.Meta.fields + ( + Keyword.created.key, + Keyword.updated.key, 'usageCount', ) dump_only = BaseKeywordSchema.Meta.dump_only + ( + Keyword.created.key, + Keyword.updated.key, ) From 70fdcf2ba170b0e084276dc2afee2b5cc236c2ac Mon Sep 17 00:00:00 2001 From: Jon Van Oast Date: Wed, 10 Jan 2024 17:00:57 -0700 Subject: [PATCH 4/8] add event trigger pull_request --- .github/workflows/testing.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 83b956f73..54e3f91b2 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -3,7 +3,11 @@ name: Testing -on: push +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] jobs: lint: From c20d5820c401463514284d6781435f2329ecd11a Mon Sep 17 00:00:00 2001 From: Veda Karteeka Gogineni Date: Wed, 10 Jan 2024 19:25:09 -0800 Subject: [PATCH 5/8] Fixed indentations as per flake8 --- app/modules/keywords/schemas.py | 11 ++++------- tests/modules/keywords/resources/test_keywords.py | 1 - 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/modules/keywords/schemas.py b/app/modules/keywords/schemas.py index afd04c19c..f884354c9 100644 --- a/app/modules/keywords/schemas.py +++ b/app/modules/keywords/schemas.py @@ -6,7 +6,7 @@ from flask_restx_patched import ModelSchema -from flask_marshmallow import base_fields +from flask_marshmallow import base_fields from .models import Keyword @@ -32,17 +32,14 @@ class DetailedKeywordSchema(BaseKeywordSchema): """ Detailed Keyword schema exposes all useful fields. """ - usageCount = base_fields.Function( - lambda kw: kw.number_referenced_dependencies(), - dump_only=True # This is a read-only field - ) - + usageCount = base_fields.Function(lambda kw: kw.number_referenced_dependencies(), + dump_only=True) class Meta(BaseKeywordSchema.Meta): fields = BaseKeywordSchema.Meta.fields + ( Keyword.created.key, Keyword.updated.key, - 'usageCount', + 'usageCount', # This is a read-only field ) dump_only = BaseKeywordSchema.Meta.dump_only + ( Keyword.created.key, diff --git a/tests/modules/keywords/resources/test_keywords.py b/tests/modules/keywords/resources/test_keywords.py index 8e05bc8da..197b218a7 100644 --- a/tests/modules/keywords/resources/test_keywords.py +++ b/tests/modules/keywords/resources/test_keywords.py @@ -72,7 +72,6 @@ def test_modify_keyword(db, flask_app_client, researcher_1, staff_user): assert response.json.get('value', None) == val2 assert response.json.get('usageCount', None) == 0 - # both of these should not be allowed (403) response = keyword_utils.patch_keyword( flask_app_client, researcher_1, guid, patch, 403 From 7712a522cefe22fe2615fa476d13b89f5e1f8157 Mon Sep 17 00:00:00 2001 From: Veda Karteeka Gogineni Date: Thu, 11 Jan 2024 20:26:52 -0800 Subject: [PATCH 6/8] Upgraded the version of isort --- .pre-commit-config.yaml | 4 ++-- app/modules/keywords/schemas.py | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7f10f4dc2..6a523d177 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,7 +25,7 @@ repos: name: pyupgrade description: Run PyUpgrade on Python code. - repo: https://github.com/pycqa/isort - rev: 5.10.1 + rev: 5.13.2 hooks: - id: isort args: [--settings-path setup.cfg] @@ -39,7 +39,7 @@ repos: entry: brunette --config=setup.cfg language: system types: [python] - - repo: https://gitlab.com/pycqa/flake8 + - repo: https://github.com/pycqa/flake8 rev: 3.8.3 hooks: - id: flake8 diff --git a/app/modules/keywords/schemas.py b/app/modules/keywords/schemas.py index f884354c9..52a449587 100644 --- a/app/modules/keywords/schemas.py +++ b/app/modules/keywords/schemas.py @@ -5,9 +5,10 @@ """ -from flask_restx_patched import ModelSchema from flask_marshmallow import base_fields +from flask_restx_patched import ModelSchema + from .models import Keyword @@ -23,7 +24,6 @@ class Meta: Keyword.guid.key, Keyword.value.key, Keyword.source.key, - ) dump_only = (Keyword.guid.key,) @@ -32,8 +32,10 @@ class DetailedKeywordSchema(BaseKeywordSchema): """ Detailed Keyword schema exposes all useful fields. """ - usageCount = base_fields.Function(lambda kw: kw.number_referenced_dependencies(), - dump_only=True) + + usageCount = base_fields.Function( + lambda kw: kw.number_referenced_dependencies(), dump_only=True + ) class Meta(BaseKeywordSchema.Meta): fields = BaseKeywordSchema.Meta.fields + ( From 1e65b964cdf902262069b8a70eeb2da54c8d2808 Mon Sep 17 00:00:00 2001 From: github-actions Date: Tue, 16 Jan 2024 19:27:07 +0000 Subject: [PATCH 7/8] Update _frontend.codex submodule to HEAD of codex-frontend@develop --- _frontend.codex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_frontend.codex b/_frontend.codex index 7b087d1c8..5dc1dc14d 160000 --- a/_frontend.codex +++ b/_frontend.codex @@ -1 +1 @@ -Subproject commit 7b087d1c8fd4ce5df8039dec4e56b326947533af +Subproject commit 5dc1dc14d92839ad7d80a51b037cf9caa358d192 From b7b1dd76f708c1fe3ced92a4e34b051962bd43d3 Mon Sep 17 00:00:00 2001 From: veda-gogineni Date: Mon, 22 Jan 2024 21:25:10 -0800 Subject: [PATCH 8/8] Letting admin to delete keyword --- app/modules/annotations/models.py | 4 +- app/modules/assets/models.py | 4 +- app/modules/users/permissions/rules.py | 1 + migrations/versions/dc91b517a7a4_.py | 73 ++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 migrations/versions/dc91b517a7a4_.py diff --git a/app/modules/annotations/models.py b/app/modules/annotations/models.py index bf7e72d57..61344228b 100644 --- a/app/modules/annotations/models.py +++ b/app/modules/annotations/models.py @@ -21,7 +21,9 @@ class AnnotationKeywords(db.Model, HoustonModel): annotation_guid = db.Column( db.GUID, db.ForeignKey('annotation.guid'), primary_key=True ) - keyword_guid = db.Column(db.GUID, db.ForeignKey('keyword.guid'), primary_key=True) + keyword_guid = db.Column( + db.GUID, db.ForeignKey('keyword.guid', ondelete='CASCADE'), primary_key=True + ) annotation = db.relationship('Annotation', back_populates='keyword_refs') keyword = db.relationship('Keyword') diff --git a/app/modules/assets/models.py b/app/modules/assets/models.py index 7cd7fb64a..d70ad593b 100644 --- a/app/modules/assets/models.py +++ b/app/modules/assets/models.py @@ -24,7 +24,9 @@ class AssetTags(db.Model, HoustonModel): asset_guid = db.Column(db.GUID, db.ForeignKey('asset.guid'), primary_key=True) - tag_guid = db.Column(db.GUID, db.ForeignKey('keyword.guid'), primary_key=True) + tag_guid = db.Column( + db.GUID, db.ForeignKey('keyword.guid', ondelete='CASCADE'), primary_key=True + ) asset = db.relationship('Asset', back_populates='tag_refs') tag = db.relationship('Keyword') diff --git a/app/modules/users/permissions/rules.py b/app/modules/users/permissions/rules.py index e999f3d72..8480b0faa 100644 --- a/app/modules/users/permissions/rules.py +++ b/app/modules/users/permissions/rules.py @@ -178,6 +178,7 @@ 'is_admin', ], ('Keyword', AccessOperation.READ): ['is_active'], + ('Keyword', AccessOperation.DELETE): ['is_admin'], ('Sighting', AccessOperation.WRITE_INTERNAL): ['is_internal'], ('Sighting', AccessOperation.READ_PRIVILEGED): ['is_staff'], ('Sighting', AccessOperation.READ): ['is_admin'], diff --git a/migrations/versions/dc91b517a7a4_.py b/migrations/versions/dc91b517a7a4_.py new file mode 100644 index 000000000..e620eb790 --- /dev/null +++ b/migrations/versions/dc91b517a7a4_.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +"""empty message + +Revision ID: dc91b517a7a4 +Revises: 53b0fec87272 +Create Date: 2024-01-22 22:51:34.690766 + +""" + +from alembic import op + +# revision identifiers, used by Alembic. +revision = 'dc91b517a7a4' +down_revision = '53b0fec87272' + + +def upgrade(): + """ + Upgrade Semantic Description: + ENTER DESCRIPTION HERE + """ + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('annotation_keywords', schema=None) as batch_op: + batch_op.drop_constraint( + 'fk_annotation_keywords_keyword_guid_keyword', type_='foreignkey' + ) + batch_op.create_foreign_key( + batch_op.f('fk_annotation_keywords_keyword_guid_keyword'), + 'keyword', + ['keyword_guid'], + ['guid'], + ondelete='CASCADE', + ) + + with op.batch_alter_table('asset_tags', schema=None) as batch_op: + batch_op.drop_constraint('fk_asset_tags_tag_guid_keyword', type_='foreignkey') + batch_op.create_foreign_key( + batch_op.f('fk_asset_tags_tag_guid_keyword'), + 'keyword', + ['tag_guid'], + ['guid'], + ondelete='CASCADE', + ) + + # ### end Alembic commands ### + + +def downgrade(): + """ + Downgrade Semantic Description: + ENTER DESCRIPTION HERE + """ + # ### commands auto generated by Alembic - please adjust! ### + with op.batch_alter_table('asset_tags', schema=None) as batch_op: + batch_op.drop_constraint( + batch_op.f('fk_asset_tags_tag_guid_keyword'), type_='foreignkey' + ) + batch_op.create_foreign_key( + 'fk_asset_tags_tag_guid_keyword', 'keyword', ['tag_guid'], ['guid'] + ) + + with op.batch_alter_table('annotation_keywords', schema=None) as batch_op: + batch_op.drop_constraint( + batch_op.f('fk_annotation_keywords_keyword_guid_keyword'), type_='foreignkey' + ) + batch_op.create_foreign_key( + 'fk_annotation_keywords_keyword_guid_keyword', + 'keyword', + ['keyword_guid'], + ['guid'], + ) + + # ### end Alembic commands ###